12 #include "flutter/display_list/testing/dl_test_snippets.h"
13 #include "fml/logging.h"
14 #include "gtest/gtest.h"
55 #include "impeller/renderer/testing/mocks.h"
57 #include "third_party/imgui/imgui.h"
78 auto image = CreateTextureForFixture(
"boston.jpg");
84 auto actual = filter->GetCoverage({});
87 ASSERT_TRUE(actual.has_value());
94 filter->SetCoverageHint(expected);
95 auto actual = filter->GetCoverage({});
97 ASSERT_TRUE(actual.has_value());
122 auto contents = std::make_unique<SolidColorContents>();
125 contents->SetGeometry(geom.get());
128 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
132 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
144 auto contents = std::make_unique<TiledTextureContents>();
146 contents->SetGeometry(geom.get());
147 contents->SetTexture(bridge);
150 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
185 auto contents = std::make_unique<SolidColorContents>();
187 contents->SetGeometry(geom.get());
191 return entity.
Render(context, pass);
193 ASSERT_TRUE(OpenPlaygroundHere(callback));
198 const Point margin(140, 180);
204 static Scalar miter_limit = 1.41421357;
207 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
209 ImGui::SliderFloat(
"Miter limit", &miter_limit, 0, 30);
210 ImGui::SliderFloat(
"Stroke width", &width, 0, 100);
211 if (ImGui::Button(
"Reset")) {
212 miter_limit = 1.41421357;
219 auto render_path = [width = width, &context, &pass, &world_matrix](
221 auto contents = std::make_unique<SolidColorContents>();
222 std::unique_ptr<Geometry> geom =
224 contents->SetGeometry(geom.get());
232 if (coverage.has_value()) {
233 auto bounds_contents = std::make_unique<SolidColorContents>();
238 bounds_contents->SetGeometry(geom.get());
239 bounds_contents->SetColor(
Color::Green().WithAlpha(0.5));
241 bounds_entity.
SetContents(std::move(bounds_contents));
242 bounds_entity.
Render(context, pass);
245 entity.
Render(context, pass);
248 const Point a_def(0, 0), b_def(0, 100), c_def(150, 0), d_def(150, -100),
334 ASSERT_TRUE(OpenPlaygroundHere(callback));
341 .
MoveTo({237.164, 125.003})
342 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
344 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
346 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
348 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
350 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
358 auto contents = std::make_shared<SolidColorContents>();
360 contents->SetGeometry(geom.get());
363 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
368 const char* input_axis[] = {
"X",
"Y",
"Z"};
369 static int rotation_axis_index = 0;
370 static float rotation = 0;
371 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
372 ImGui::SliderFloat(
"Rotation", &rotation, -
kPi,
kPi);
373 ImGui::Combo(
"Rotation Axis", &rotation_axis_index, input_axis,
374 sizeof(input_axis) /
sizeof(
char*));
376 switch (rotation_axis_index) {
387 rotation_matrix =
Matrix{};
391 if (ImGui::Button(
"Reset")) {
395 Matrix current_transform =
399 pass.GetRenderTargetSize().height / 2.0)));
400 Matrix result_transform = current_transform * rotation_matrix;
409 auto contents = std::make_shared<SolidColorContents>();
411 contents->SetGeometry(geom.get());
414 return entity.
Render(context, pass);
416 ASSERT_TRUE(OpenPlaygroundHere(callback));
423 .
MoveTo({359.934, 96.6335})
424 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
426 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
428 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
430 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
432 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
434 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
436 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
438 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
440 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
442 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
444 .
LineTo({332.237, 102.601})
445 .
LineTo({321.778, 102.601})
446 .
LineTo({321.778, 100.382})
447 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
449 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
451 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
453 .
LineTo({310.017, 105.94})
454 .
LineTo({309.779, 105.427})
455 .
LineTo({314.403, 101.651})
456 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
458 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
460 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
461 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
463 .
LineTo({299.105, 107.578})
464 .
LineTo({298.867, 107.065})
465 .
LineTo({302.394, 104.185})
466 .
LineTo({302.412, 104.171})
467 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
469 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
470 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
472 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
474 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
476 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
478 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
480 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
482 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
484 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
486 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
488 .
LineTo({271.717, 113.449})
489 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
491 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
493 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
495 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
497 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
499 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
501 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
503 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
505 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
507 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
509 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
510 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
512 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
514 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
516 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
518 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
520 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
521 .
LineTo({237.164, 125.003})
522 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
524 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
526 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
528 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
530 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
535 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
538 .MoveTo({337.336, 124.143})
539 .CubicCurveTo({337.274, 122.359}, {338.903, 121.511},
541 .CubicCurveTo({338.903, 121.511}, {338.96, 123.303},
544 .MoveTo({340.082, 121.849})
545 .CubicCurveTo({340.074, 121.917}, {340.062, 121.992},
547 .CubicCurveTo({340.039, 122.109}, {340.031, 122.142},
549 .CubicCurveTo({340.005, 122.26}, {339.98, 122.346},
551 .CubicCurveTo({339.941, 122.473}, {339.931, 122.507},
553 .CubicCurveTo({339.873, 122.672}, {339.819, 122.804},
555 .CubicCurveTo({339.747, 122.944}, {339.743, 122.949},
557 .CubicCurveTo({339.674, 123.08}, {339.593, 123.205},
559 .CubicCurveTo({339.473, 123.366}, {339.441, 123.401},
561 .CubicCurveTo({339.332, 123.534}, {339.243, 123.625},
563 .CubicCurveTo({339.105, 123.75}, {339.068, 123.786},
565 .CubicCurveTo({338.881, 123.937}, {338.724, 124.048},
567 .CubicCurveTo({338.532, 123.959}, {338.554, 123.79},
569 .CubicCurveTo({338.58, 123.625}, {338.58, 123.625}, {338.58, 123.625})
570 .CubicCurveTo({338.607, 123.455}, {338.65, 123.299},
572 .CubicCurveTo({338.708, 123.14}, {338.71, 123.127},
574 .CubicCurveTo({338.769, 122.971}, {338.833, 122.838},
576 .CubicCurveTo({338.911, 122.702}, {338.916, 122.69200000000001},
578 .CubicCurveTo({338.996, 122.557}, {339.072, 122.444},
580 .CubicCurveTo({339.161, 122.333}, {339.166, 122.326},
582 .CubicCurveTo({339.256, 122.215}, {339.339, 122.12},
584 .CubicCurveTo({339.428, 122.033}, {339.431, 122.03},
586 .CubicCurveTo({339.785, 121.687}, {340.106, 121.511},
588 .CubicCurveTo({340.106, 121.511}, {340.107, 121.645},
591 .MoveTo({340.678, 113.245})
592 .CubicCurveTo({340.594, 113.488}, {340.356, 113.655},
594 .CubicCurveTo({339.817, 113.948}, {339.465, 114.059},
596 .CubicCurveTo({338.251, 114.379}, {337.34, 114.516},
598 .CubicCurveTo({335.761, 114.516}, {335.072, 114.527},
600 .CubicCurveTo({334.125, 114.508}, {333.862, 114.462},
602 .CubicCurveTo({332.865, 114.318}, {332.096, 114.184},
604 .CubicCurveTo({330.979, 113.695}, {330.442, 113.34},
606 .CubicCurveTo({331.135, 111.755}, {333.219, 112.946},
608 .CubicCurveTo({334.54, 113.816}, {334.554, 113.8}, {334.569, 113.784})
609 .CubicCurveTo({333.38, 112.708}, {331.749, 110.985},
611 .CubicCurveTo({333.769, 109.82}, {334.713, 111.93},
613 .CubicCurveTo({334.915, 111.889}, {334.59, 109.636},
615 .CubicCurveTo({336.733, 109.636}, {336.408, 111.889},
617 .CubicCurveTo({336.609, 111.93}, {337.553, 109.82},
619 .CubicCurveTo({339.574, 110.984}, {337.942, 112.708},
621 .CubicCurveTo({336.768, 113.8}, {336.782, 113.816},
623 .CubicCurveTo({338.104, 112.946}, {340.187, 111.755},
625 .CubicCurveTo({340.71, 112.95}, {340.728, 113.102},
628 .MoveTo({346.357, 106.771})
629 .CubicCurveTo({346.295, 104.987}, {347.924, 104.139},
631 .CubicCurveTo({347.924, 104.139}, {347.982, 105.931},
634 .MoveTo({347.56, 106.771})
635 .CubicCurveTo({347.498, 104.987}, {349.127, 104.139},
637 .CubicCurveTo({349.127, 104.139}, {349.185, 105.931},
646 auto contents = std::make_shared<SolidColorContents>();
648 contents->SetGeometry(geom.get());
651 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
659 ASSERT_EQ(path_geometry->GetStrokeCap(),
Cap::kButt);
660 ASSERT_EQ(path_geometry->GetStrokeJoin(),
Join::kMiter);
672 ASSERT_EQ(path_geometry->GetStrokeCap(),
Cap::kRound);
680 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
687 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 8);
694 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
699 std::vector<const char*> blend_mode_names;
700 std::vector<BlendMode> blend_mode_values;
713 blend_mode_names.push_back(
"Clear");
716 blend_mode_names.push_back(
"Source");
719 blend_mode_names.push_back(
"Destination");
722 blend_mode_names.push_back(
"SourceOver");
725 blend_mode_names.push_back(
"DestinationOver");
728 blend_mode_names.push_back(
"SourceIn");
731 blend_mode_names.push_back(
"DestinationIn");
734 blend_mode_names.push_back(
"SourceOut");
737 blend_mode_names.push_back(
"DestinationOut");
740 blend_mode_names.push_back(
"SourceATop");
743 blend_mode_names.push_back(
"DestinationATop");
746 blend_mode_names.push_back(
"Xor");
749 blend_mode_names.push_back(
"Plus");
752 blend_mode_names.push_back(
"Modulate");
759 auto draw_rect = [&context, &pass, &world_matrix](
766 auto r = rect.GetLTRB();
777 pass.SetCommandLabel(
"Blended Rectangle");
779 options.blend_mode = blend_mode;
782 pass.SetVertexBuffer(
785 VS::FrameInfo frame_info;
786 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
789 FS::FragInfo frag_info;
790 frag_info.color = color.Premultiply();
793 return pass.Draw().ok();
796 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
797 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
798 ImGui::ColorEdit4(
"Color 1",
reinterpret_cast<float*
>(&color1));
799 ImGui::ColorEdit4(
"Color 2",
reinterpret_cast<float*
>(&color2));
800 static int current_blend_index = 3;
801 ImGui::ListBox(
"Blending mode", ¤t_blend_index,
802 blend_mode_names.data(), blend_mode_names.size());
805 BlendMode selected_mode = blend_mode_values[current_blend_index];
818 pass.GetRenderTargetSize().height),
826 ASSERT_TRUE(OpenPlaygroundHere(callback));
831 static float scale = 20;
833 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
834 ImGui::SliderFloat(
"Scale", &
scale, 1, 100);
841 .CubicCurveTo({98.50862885295136, 34.81812293973836},
842 {99.46822048142015, 33.85863261475589},
843 {99.46822048142015, 32.67499810206613})
844 .CubicCurveTo({99.46822048142015, 31.491363589376355},
845 {98.50862885295136, 30.53187326439389},
846 {97.32499434685802, 30.531998226542708})
847 .CubicCurveTo({96.14153655073771, 30.532123170035373},
848 {95.18222070648729, 31.491540299350355},
849 {95.18222070648729, 32.67499810206613})
850 .CubicCurveTo({95.18222070648729, 33.85845590478189},
851 {96.14153655073771, 34.81787303409686},
852 {97.32499434685802, 34.81799797758954})
860 auto contents = std::make_shared<SolidColorContents>();
862 contents->SetGeometry(geom.get());
865 return entity.
Render(context, pass);
867 ASSERT_TRUE(OpenPlaygroundHere(callback));
871 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
872 auto boston = CreateTextureForFixture(
"boston.jpg");
873 auto kalimba = CreateTextureForFixture(
"kalimba.jpg");
874 ASSERT_TRUE(bridge && boston && kalimba);
892 entity.SetContents(blend1);
893 return entity.Render(context, pass);
895 ASSERT_TRUE(OpenPlaygroundHere(callback));
900 CreateTextureForFixture(
"boston.jpg",
true);
904 const char* input_type_names[] = {
"Texture",
"Solid Color"};
905 const char* blur_type_names[] = {
"Image blur",
"Mask blur"};
906 const char* pass_variation_names[] = {
"New"};
907 const char* blur_style_names[] = {
"Normal",
"Solid",
"Outer",
"Inner"};
908 const char* tile_mode_names[] = {
"Clamp",
"Repeat",
"Mirror",
"Decal"};
917 static int selected_input_type = 0;
919 static int selected_blur_type = 0;
920 static int selected_pass_variation = 0;
921 static bool combined_sigma =
false;
922 static float blur_amount_coarse[2] = {0, 0};
923 static float blur_amount_fine[2] = {10, 10};
924 static int selected_blur_style = 0;
925 static int selected_tile_mode = 3;
926 static Color cover_color(1, 0, 0, 0.2);
927 static Color bounds_color(0, 1, 0, 0.1);
928 static float offset[2] = {500, 400};
929 static float rotation = 0;
930 static float scale[2] = {0.65, 0.65};
931 static float skew[2] = {0, 0};
932 static float path_rect[4] = {0, 0,
933 static_cast<float>(boston->GetSize().width),
934 static_cast<float>(boston->GetSize().height)};
936 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
938 ImGui::Combo(
"Input type", &selected_input_type, input_type_names,
939 sizeof(input_type_names) /
sizeof(
char*));
940 if (selected_input_type == 0) {
941 ImGui::SliderFloat(
"Input opacity", &input_color.
alpha, 0, 1);
943 ImGui::ColorEdit4(
"Input color",
944 reinterpret_cast<float*
>(&input_color));
946 ImGui::Combo(
"Blur type", &selected_blur_type, blur_type_names,
947 sizeof(blur_type_names) /
sizeof(
char*));
948 if (selected_blur_type == 0) {
949 ImGui::Combo(
"Pass variation", &selected_pass_variation,
950 pass_variation_names,
951 sizeof(pass_variation_names) /
sizeof(
char*));
953 ImGui::Checkbox(
"Combined sigma", &combined_sigma);
954 if (combined_sigma) {
955 ImGui::SliderFloat(
"Sigma (coarse)", blur_amount_coarse, 0, 1000);
956 ImGui::SliderFloat(
"Sigma (fine)", blur_amount_fine, 0, 10);
957 blur_amount_coarse[1] = blur_amount_coarse[0];
958 blur_amount_fine[1] = blur_amount_fine[0];
960 ImGui::SliderFloat2(
"Sigma (coarse)", blur_amount_coarse, 0, 1000);
961 ImGui::SliderFloat2(
"Sigma (fine)", blur_amount_fine, 0, 10);
963 ImGui::Combo(
"Blur style", &selected_blur_style, blur_style_names,
964 sizeof(blur_style_names) /
sizeof(
char*));
965 ImGui::Combo(
"Tile mode", &selected_tile_mode, tile_mode_names,
966 sizeof(tile_mode_names) /
sizeof(
char*));
967 ImGui::ColorEdit4(
"Cover color",
reinterpret_cast<float*
>(&cover_color));
968 ImGui::ColorEdit4(
"Bounds color ",
969 reinterpret_cast<float*
>(&bounds_color));
970 ImGui::SliderFloat2(
"Translation",
offset, 0,
971 pass.GetRenderTargetSize().width);
972 ImGui::SliderFloat(
"Rotation", &rotation, 0,
kPi * 2);
973 ImGui::SliderFloat2(
"Scale",
scale, 0, 3);
974 ImGui::SliderFloat2(
"Skew", skew, -3, 3);
975 ImGui::SliderFloat4(
"Path XYWH", path_rect, -1000, 1000);
979 auto blur_sigma_x =
Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
980 auto blur_sigma_y =
Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
982 std::shared_ptr<Contents> input;
986 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
988 std::unique_ptr<Geometry> solid_color_input;
989 if (selected_input_type == 0) {
990 auto texture = std::make_shared<TextureContents>();
992 texture->SetDestinationRect(input_rect);
993 texture->SetTexture(boston);
994 texture->SetOpacity(input_color.
alpha);
997 input_size = input_rect.GetSize();
999 auto fill = std::make_shared<SolidColorContents>();
1000 fill->SetColor(input_color);
1004 fill->SetGeometry(solid_color_input.get());
1007 input_size = input_rect.GetSize();
1010 std::shared_ptr<FilterContents> blur;
1011 switch (selected_pass_variation) {
1013 blur = std::make_shared<GaussianBlurFilterContents>(
1014 blur_sigma_x.sigma, blur_sigma_y.sigma,
1015 tile_modes[selected_tile_mode], blur_styles[selected_blur_style],
1022 tile_modes[selected_tile_mode], blur_styles[selected_blur_style]);
1029 blur_styles[selected_blur_style]);
1038 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1044 entity.
Render(context, pass);
1049 std::unique_ptr<Geometry> geom =
1051 auto contents = std::make_shared<SolidColorContents>();
1052 contents->SetColor(cover_color);
1053 contents->SetGeometry(geom.get());
1056 cover_entity.
Render(context, pass);
1060 std::optional<Rect> target_contents_coverage =
1062 if (target_contents_coverage.has_value()) {
1065 .
AddRect(target_contents->GetCoverage(entity).value())
1067 auto contents = std::make_shared<SolidColorContents>();
1068 contents->SetColor(bounds_color);
1069 contents->SetGeometry(geom.get());
1073 bounds_entity.
Render(context, pass);
1078 ASSERT_TRUE(OpenPlaygroundHere(callback));
1082 auto boston = CreateTextureForFixture(
"boston.jpg");
1083 ASSERT_TRUE(boston);
1086 const char* morphology_type_names[] = {
"Dilate",
"Erode"};
1091 static int selected_morphology_type = 0;
1092 static float radius[2] = {20, 20};
1093 static Color cover_color(1, 0, 0, 0.2);
1094 static Color bounds_color(0, 1, 0, 0.1);
1095 static float offset[2] = {500, 400};
1096 static float rotation = 0;
1097 static float scale[2] = {0.65, 0.65};
1098 static float skew[2] = {0, 0};
1099 static float path_rect[4] = {0, 0,
1100 static_cast<float>(boston->GetSize().width),
1101 static_cast<float>(boston->GetSize().height)};
1102 static float effect_transform_scale = 1;
1104 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1106 ImGui::Combo(
"Morphology type", &selected_morphology_type,
1107 morphology_type_names,
1108 sizeof(morphology_type_names) /
sizeof(
char*));
1109 ImGui::SliderFloat2(
"Radius", radius, 0, 200);
1110 ImGui::SliderFloat(
"Input opacity", &input_color.
alpha, 0, 1);
1111 ImGui::ColorEdit4(
"Cover color",
reinterpret_cast<float*
>(&cover_color));
1112 ImGui::ColorEdit4(
"Bounds color ",
1113 reinterpret_cast<float*
>(&bounds_color));
1114 ImGui::SliderFloat2(
"Translation",
offset, 0,
1115 pass.GetRenderTargetSize().width);
1116 ImGui::SliderFloat(
"Rotation", &rotation, 0,
kPi * 2);
1117 ImGui::SliderFloat2(
"Scale",
scale, 0, 3);
1118 ImGui::SliderFloat2(
"Skew", skew, -3, 3);
1119 ImGui::SliderFloat4(
"Path XYWH", path_rect, -1000, 1000);
1120 ImGui::SliderFloat(
"Effect transform scale", &effect_transform_scale, 0,
1125 std::shared_ptr<Contents> input;
1129 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1130 auto texture = std::make_shared<TextureContents>();
1132 texture->SetDestinationRect(input_rect);
1133 texture->SetTexture(boston);
1134 texture->SetOpacity(input_color.
alpha);
1137 input_size = input_rect.GetSize();
1141 morphology_types[selected_morphology_type]);
1143 Vector2{effect_transform_scale, effect_transform_scale}));
1156 entity.
Render(context, pass);
1161 std::unique_ptr<Geometry> geom =
1163 auto cover_contents = std::make_shared<SolidColorContents>();
1164 cover_contents->SetColor(cover_color);
1165 cover_contents->SetGeometry(geom.get());
1168 cover_entity.
Render(context, pass);
1174 .
AddRect(contents->GetCoverage(entity).value())
1176 auto bounds_contents = std::make_shared<SolidColorContents>();
1177 bounds_contents->SetColor(bounds_color);
1178 bounds_contents->SetGeometry(bounds_geom.get());
1179 bounds_entity.
SetContents(std::move(bounds_contents));
1182 bounds_entity.
Render(context, pass);
1186 ASSERT_TRUE(OpenPlaygroundHere(callback));
1198 entity.
SetContents(std::make_shared<SolidColorContents>());
1209 auto contents = std::make_unique<SolidColorContents>();
1210 contents->SetGeometry(geometry.get());
1216 ASSERT_TRUE(actual.has_value());
1227 auto contents = std::make_unique<SolidColorContents>();
1228 contents->SetGeometry(geometry.get());
1235 ASSERT_TRUE(actual.has_value());
1246 auto contents = std::make_unique<SolidColorContents>();
1247 contents->SetGeometry(geometry.get());
1253 ASSERT_TRUE(actual.has_value());
1259 auto fill = std::make_shared<SolidColorContents>();
1262 fill->SetGeometry(geom.get());
1270 auto actual = border_mask_blur->GetCoverage(e);
1272 ASSERT_TRUE(actual.has_value());
1279 auto actual = border_mask_blur->GetCoverage(e);
1280 auto expected =
Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1281 ASSERT_TRUE(actual.has_value());
1289 auto fill = std::make_shared<SolidColorContents>();
1294 fill->SetGeometry(geom.get());
1296 auto coverage = fill->GetCoverage({});
1297 ASSERT_TRUE(coverage.has_value());
1303 auto fill = std::make_shared<SolidColorContents>();
1307 fill->SetGeometry(geom.get());
1315 ASSERT_TRUE(coverage.has_value());
1321 auto fill = std::make_shared<SolidColorContents>();
1325 fill->SetGeometry(geom.get());
1327 auto coverage = fill->GetCoverage({});
1328 ASSERT_FALSE(coverage.has_value());
1335 static float corner_radius = 100;
1337 static bool show_coverage =
false;
1340 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1341 ImGui::SliderFloat(
"Corner radius", &corner_radius, 0, 300);
1342 ImGui::SliderFloat(
"Blur radius", &
blur_radius, 0, 300);
1343 ImGui::ColorEdit4(
"Color",
reinterpret_cast<Scalar*
>(&color));
1344 ImGui::Checkbox(
"Show coverage", &show_coverage);
1345 if (show_coverage) {
1346 ImGui::ColorEdit4(
"Coverage color",
1347 reinterpret_cast<Scalar*
>(&coverage_color));
1353 auto [top_left, bottom_right] =
1356 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1358 auto contents = std::make_unique<SolidRRectBlurContents>();
1359 contents->SetRRect(rect, {corner_radius, corner_radius});
1360 contents->SetColor(color);
1366 entity.
Render(context, pass);
1369 if (show_coverage && coverage.has_value()) {
1370 auto bounds_contents = std::make_unique<SolidColorContents>();
1373 bounds_contents->SetGeometry(geom.get());
1374 bounds_contents->SetColor(coverage_color.
Premultiply());
1376 bounds_entity.
SetContents(std::move(bounds_contents));
1377 bounds_entity.
Render(context, pass);
1382 ASSERT_TRUE(OpenPlaygroundHere(callback));
1387 auto fill = std::make_shared<SolidColorContents>();
1390 fill->SetGeometry(geom.get());
1408 auto actual = filter->GetCoverage(e);
1411 ASSERT_TRUE(actual.has_value());
1416 auto bay_bridge = CreateTextureForFixture(
"bay_bridge.jpg");
1417 ASSERT_TRUE(bay_bridge);
1427 static float offset[2] = {500, 400};
1428 static float rotation = 0;
1429 static float scale[2] = {0.65, 0.65};
1430 static float skew[2] = {0, 0};
1433 ImGui::Begin(
"Color Matrix",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1435 std::string label =
"##1";
1436 for (
int i = 0; i < 20; i += 5) {
1437 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1438 &(color_matrix.
array[i]), 5,
nullptr,
nullptr,
1443 ImGui::SliderFloat2(
"Translation", &
offset[0], 0,
1444 pass.GetRenderTargetSize().width);
1445 ImGui::SliderFloat(
"Rotation", &rotation, 0,
kPi * 2);
1446 ImGui::SliderFloat2(
"Scale", &
scale[0], 0, 3);
1447 ImGui::SliderFloat2(
"Skew", &skew[0], -3, 3);
1465 entity.
Render(context, pass);
1470 ASSERT_TRUE(OpenPlaygroundHere(callback));
1477 auto fill = std::make_shared<SolidColorContents>();
1478 fill->SetGeometry(geom.get());
1488 auto actual = filter->GetCoverage(e);
1491 ASSERT_TRUE(actual.has_value());
1496 auto image = CreateTextureForFixture(
"kalimba.jpg");
1519 return entity_left.
Render(context, pass) &&
1520 entity_right.
Render(context, pass);
1523 ASSERT_TRUE(OpenPlaygroundHere(callback));
1528 auto fill = std::make_shared<SolidColorContents>();
1531 fill->SetGeometry(geom.get());
1541 auto actual = filter->GetCoverage(e);
1544 ASSERT_TRUE(actual.has_value());
1549 auto image = CreateTextureForFixture(
"embarcadero.jpg");
1572 return entity_left.
Render(context, pass) &&
1573 entity_right.
Render(context, pass);
1576 ASSERT_TRUE(OpenPlaygroundHere(callback));
1581 switch (yuv_color_space) {
1583 yuv.
x = rgb.
x * 0.299 + rgb.
y * 0.587 + rgb.
z * 0.114;
1584 yuv.
y = rgb.
x * -0.169 + rgb.
y * -0.331 + rgb.
z * 0.5 + 0.5;
1585 yuv.
z = rgb.
x * 0.5 + rgb.
y * -0.419 + rgb.
z * -0.081 + 0.5;
1588 yuv.
x = rgb.
x * 0.257 + rgb.
y * 0.516 + rgb.
z * 0.100 + 0.063;
1589 yuv.
y = rgb.
x * -0.145 + rgb.
y * -0.291 + rgb.
z * 0.439 + 0.5;
1590 yuv.
z = rgb.
x * 0.429 + rgb.
y * -0.368 + rgb.
z * -0.071 + 0.5;
1599 Vector3 red = {244.0 / 255.0, 67.0 / 255.0, 54.0 / 255.0};
1600 Vector3 green = {76.0 / 255.0, 175.0 / 255.0, 80.0 / 255.0};
1601 Vector3 blue = {33.0 / 255.0, 150.0 / 255.0, 243.0 / 255.0};
1602 Vector3 white = {1.0, 1.0, 1.0};
1607 std::vector<Vector3> yuvs{red_yuv, green_yuv, blue_yuv, white_yuv};
1608 std::vector<uint8_t> y_data;
1609 std::vector<uint8_t> uv_data;
1610 for (
int i = 0; i < 4; i++) {
1612 uint8_t y = std::round(yuv.x * 255.0);
1613 uint8_t u = std::round(yuv.y * 255.0);
1614 uint8_t v = std::round(yuv.z * 255.0);
1615 for (
int j = 0; j < 16; j++) {
1616 y_data.push_back(y);
1618 for (
int j = 0; j < 8; j++) {
1619 uv_data.push_back(j % 2 == 0 ? u : v);
1623 auto blit_pass = cmd_buffer->CreateBlitPass();
1628 y_texture_descriptor.
size = {8, 8};
1631 auto y_mapping = std::make_shared<fml::DataMapping>(y_data);
1632 auto y_mapping_buffer =
1640 uv_texture_descriptor.
size = {4, 4};
1643 auto uv_mapping = std::make_shared<fml::DataMapping>(uv_data);
1644 auto uv_mapping_buffer =
1649 if (!blit_pass->EncodeCommands() ||
1651 FML_DLOG(ERROR) <<
"Could not copy contents into Y/UV texture.";
1654 return {y_texture, uv_texture};
1661 <<
"YUV to RGB filter is not supported on OpenGLES backend yet.";
1667 for (
int i = 0; i < 2; i++) {
1668 auto yuv_color_space = yuv_color_space_array[i];
1672 textures[0], textures[1], yuv_color_space);
1675 auto snapshot = filter_contents->RenderToSnapshot(context, filter_entity);
1679 contents->SetTexture(snapshot->texture);
1680 contents->SetSourceRect(
Rect::MakeSize(snapshot->texture->GetSize()));
1684 entity.
Render(context, pass);
1688 ASSERT_TRUE(OpenPlaygroundHere(callback));
1692 auto runtime_stages =
1693 OpenAssetAsRuntimeStage(
"runtime_stage_example.frag.iplr");
1694 auto runtime_stage =
1696 ASSERT_TRUE(runtime_stage);
1697 ASSERT_TRUE(runtime_stage->IsDirty());
1699 bool expect_dirty =
true;
1705 EXPECT_EQ(runtime_stage->IsDirty(), expect_dirty);
1707 auto contents = std::make_shared<RuntimeEffectContents>();
1708 contents->SetGeometry(geom.get());
1709 contents->SetRuntimeStage(runtime_stage);
1711 struct FragUniforms {
1715 .iResolution =
Vector2(GetWindowSize().width, GetWindowSize().height),
1716 .iTime =
static_cast<Scalar>(GetSecondsElapsed()),
1718 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1719 uniform_data->resize(
sizeof(FragUniforms));
1720 memcpy(uniform_data->data(), &frag_uniforms,
sizeof(FragUniforms));
1721 contents->SetUniformData(uniform_data);
1725 bool result = contents->Render(context, entity, pass);
1728 first_pipeline = pass.GetCommands().back().pipeline;
1730 EXPECT_EQ(pass.GetCommands().back().pipeline, first_pipeline);
1732 expect_dirty =
false;
1737 auto content_context = GetContentContext();
1740 content_context->GetRenderTargetCache()->CreateOffscreen(
1741 *content_context->GetContext(), {1, 1}, 1u);
1743 testing::MockRenderPass mock_pass(GetContext(), target);
1744 callback(*content_context, mock_pass);
1745 callback(*content_context, mock_pass);
1748 runtime_stages = OpenAssetAsRuntimeStage(
"runtime_stage_example.frag.iplr");
1752 ASSERT_TRUE(runtime_stage->IsDirty());
1753 expect_dirty =
true;
1755 callback(*content_context, mock_pass);
1760 auto runtime_stages =
1761 OpenAssetAsRuntimeStage(
"runtime_stage_example.frag.iplr");
1762 auto runtime_stage =
1764 ASSERT_TRUE(runtime_stage);
1765 ASSERT_TRUE(runtime_stage->IsDirty());
1767 auto contents = std::make_shared<RuntimeEffectContents>();
1769 contents->SetGeometry(geom.get());
1770 contents->SetRuntimeStage(runtime_stage);
1772 struct FragUniforms {
1776 .iResolution =
Vector2(GetWindowSize().width, GetWindowSize().height),
1777 .iTime =
static_cast<Scalar>(GetSecondsElapsed()),
1779 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1780 uniform_data->resize(
sizeof(FragUniforms));
1781 memcpy(uniform_data->data(), &frag_uniforms,
sizeof(FragUniforms));
1782 contents->SetUniformData(uniform_data);
1790 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
1791 *GetContext(), {GetWindowSize().width, GetWindowSize().height}, 1,
1792 "RuntimeEffect Texture");
1793 testing::MockRenderPass pass(GetContext(), target);
1795 ASSERT_TRUE(contents->Render(*GetContentContext(), entity, pass));
1796 ASSERT_EQ(pass.GetCommands().size(), 1u);
1797 const auto& command = pass.GetCommands()[0];
1798 ASSERT_TRUE(command.pipeline->GetDescriptor()
1799 .GetDepthStencilAttachmentDescriptor()
1801 ASSERT_TRUE(command.pipeline->GetDescriptor()
1802 .GetFrontStencilAttachmentDescriptor()
1807 auto runtime_stages =
1808 OpenAssetAsRuntimeStage(
"runtime_stage_example.frag.iplr");
1809 auto runtime_stage =
1811 ASSERT_TRUE(runtime_stage);
1812 ASSERT_TRUE(runtime_stage->IsDirty());
1814 auto contents = std::make_shared<RuntimeEffectContents>();
1815 contents->SetRuntimeStage(runtime_stage);
1817 EXPECT_TRUE(contents->BootstrapShader(*GetContentContext()));
1822 GTEST_SKIP() <<
"Test only applies to Vulkan";
1825 auto runtime_stages =
1826 OpenAssetAsRuntimeStage(
"runtime_stage_example.frag.iplr");
1827 auto runtime_stage =
1829 ASSERT_TRUE(runtime_stage);
1830 ASSERT_TRUE(runtime_stage->IsDirty());
1832 auto contents = std::make_shared<RuntimeEffectContents>();
1834 contents->SetGeometry(geom.get());
1835 contents->SetRuntimeStage(runtime_stage);
1837 struct FragUniforms {
1841 .iResolution =
Vector2(GetWindowSize().width, GetWindowSize().height),
1842 .iTime =
static_cast<Scalar>(GetSecondsElapsed()),
1844 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1845 uniform_data->resize(
sizeof(FragUniforms));
1846 memcpy(uniform_data->data(), &frag_uniforms,
sizeof(FragUniforms));
1849 uniform_data, GetContentContext()->GetTransientsBuffer(),
1850 runtime_stage->GetUniforms()[0]);
1860 auto image = CreateTextureForFixture(
"boston.jpg");
1870 return entity.
Render(context, pass);
1872 ASSERT_TRUE(OpenPlaygroundHere(callback));
1876 auto image = CreateTextureForFixture(
"boston.jpg");
1886 return entity.
Render(context, pass);
1888 ASSERT_TRUE(OpenPlaygroundHere(callback));
1892 auto image = CreateTextureForFixture(
"boston.jpg");
1902 return entity.
Render(context, pass);
1904 ASSERT_TRUE(OpenPlaygroundHere(callback));
1908 auto image = CreateTextureForFixture(
"boston.jpg");
1918 return entity.
Render(context, pass);
1920 ASSERT_TRUE(OpenPlaygroundHere(callback));
1924 auto image = CreateTextureForFixture(
"boston.jpg");
1934 return entity.
Render(context, pass);
1936 ASSERT_TRUE(OpenPlaygroundHere(callback));
1955 auto coverage = geometry->GetCoverage(
transform);
1966 EXPECT_TRUE(contents.
IsOpaque(matrix));
1968 EXPECT_FALSE(contents.
IsOpaque(matrix));
1977 EXPECT_FALSE(contents.
IsOpaque(matrix));
1987 EXPECT_FALSE(contents.
IsOpaque(matrix));
1989 EXPECT_FALSE(contents.
IsOpaque(matrix));
1998 EXPECT_FALSE(contents.
IsOpaque(matrix));
2008 EXPECT_TRUE(contents.
IsOpaque(matrix));
2010 EXPECT_FALSE(contents.
IsOpaque(matrix));
2013 EXPECT_FALSE(contents.
IsOpaque(matrix));
2022 EXPECT_FALSE(contents.
IsOpaque(matrix));
2032 EXPECT_TRUE(contents.
IsOpaque(matrix));
2034 EXPECT_FALSE(contents.
IsOpaque(matrix));
2037 EXPECT_FALSE(contents.
IsOpaque(matrix));
2046 EXPECT_FALSE(contents.
IsOpaque(matrix));
2056 EXPECT_TRUE(contents.
IsOpaque(matrix));
2058 EXPECT_FALSE(contents.
IsOpaque(matrix));
2061 EXPECT_FALSE(contents.
IsOpaque(matrix));
2070 EXPECT_FALSE(contents.
IsOpaque(matrix));
2075 auto bay_bridge = CreateTextureForFixture(
"bay_bridge.jpg");
2081 EXPECT_FALSE(contents.
IsOpaque(matrix));
2085 std::vector<Point> points = {{10, 20}, {100, 200}};
2095 auto src_contents = std::make_shared<SolidColorContents>();
2097 src_contents->SetGeometry(src_geom.get());
2100 auto dst_contents = std::make_shared<SolidColorContents>();
2102 dst_contents->SetGeometry(dst_geom.get());
2109 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2121 auto content_context = GetContentContext();
2123 auto default_gyph = content_context->GetGlyphAtlasPipeline({
2125 .has_depth_stencil_attachments =
false,
2127 auto alt_gyph = content_context->GetGlyphAtlasPipeline(
2129 .has_depth_stencil_attachments =
true});
2131 EXPECT_NE(default_gyph, alt_gyph);
2132 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2133 alt_gyph->GetDescriptor().GetSpecializationConstants());
2135 auto use_a8 = GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() ==
2138 std::vector<Scalar> expected_constants = {
static_cast<Scalar>(use_a8)};
2139 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2140 expected_constants);
2144 auto content_context = GetContentContext();
2145 auto default_color_burn = content_context->GetMorphologyFilterPipeline({
2149 auto decal_supported =
static_cast<Scalar>(
2150 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2151 std::vector<Scalar> expected_constants = {decal_supported};
2152 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2153 expected_constants);
2161 auto hash_a = opts.
ToKey();
2164 auto hash_b = opts.
ToKey();
2167 auto hash_c = opts.
ToKey();
2170 auto hash_d = opts.
ToKey();
2172 EXPECT_NE(hash_a, hash_b);
2173 EXPECT_NE(hash_b, hash_c);
2174 EXPECT_NE(hash_c, hash_d);
2191 bool expected_layout =
false;
2193 FragmentShader::kDescriptorSetLayouts) {
2194 if (layout.binding == 64 &&
2196 expected_layout =
true;
2199 EXPECT_TRUE(expected_layout);
2205 testing::MockRenderPass mock_pass(GetContext(), target);
2207 auto get_result = [
this, &mock_pass](
const Path& path) {
2210 return geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2239 GTEST_SKIP() <<
"Validation is only fatal on Vulkan backend.";
2244 GetContentContext()->GetBlendColorBurnPipeline({
2246 .has_depth_stencil_attachments =
false,
2262 GetContentContext()->GetRenderTargetCache()->CreateOffscreen(
2263 *GetContext(), {1, 1}, 1u);
2264 testing::MockRenderPass render_pass(GetContext(), target);
2265 auto position_result =
2266 geom->GetPositionBuffer(*GetContentContext(), entity, render_pass);
2268 EXPECT_EQ(position_result.vertex_buffer.vertex_count, 0u);
2280 auto contents = std::make_shared<SolidColorContents>();
2282 contents->SetGeometry(geom.get());
2289 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2295 static float alpha = 10;
2296 static float beta = 10;
2297 static float radius = 40;
2298 static int degree = 4;
2301 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2302 ImGui::SliderFloat(
"Alpha", &alpha, 0, 100);
2303 ImGui::SliderFloat(
"Beta", &beta, 0, 100);
2304 ImGui::SliderInt(
"Degreee", °ree, 1, 20);
2305 ImGui::SliderFloat(
"Radius", &radius, 0, 400);
2306 ImGui::ColorEdit4(
"Color",
reinterpret_cast<float*
>(&color));
2309 auto contents = std::make_shared<SolidColorContents>();
2310 std::unique_ptr<SuperellipseGeometry> geom =
2311 std::make_unique<SuperellipseGeometry>(
Point{400, 400}, radius, degree,
2313 contents->SetColor(color);
2314 contents->SetGeometry(geom.get());
2319 return entity.
Render(context, pass);
2322 ASSERT_TRUE(OpenPlaygroundHere(callback));
2328 static int style_index = 0;
2329 static float center[2] = {830, 830};
2330 static float size[2] = {600, 600};
2331 static bool horizontal_symmetry =
true;
2332 static bool vertical_symmetry =
true;
2333 static bool corner_symmetry =
true;
2335 const char* style_options[] = {
"Fill",
"Stroke"};
2339 static std::array<float, 2> radius_tl = {200};
2340 static std::array<float, 2> radius_tr;
2341 static std::array<float, 2> radius_bl;
2342 static std::array<float, 2> radius_br;
2344 auto AddRadiusControl = [](std::array<float, 2>& radii,
const char* tb_name,
2345 const char* lr_name) {
2346 std::string name =
"Radius";
2347 if (!horizontal_symmetry || !vertical_symmetry) {
2350 if (!vertical_symmetry) {
2351 name = name +
" " + tb_name;
2353 if (!horizontal_symmetry) {
2354 name = name +
" " + lr_name;
2356 if (corner_symmetry) {
2357 ImGui::SliderFloat(name.c_str(), radii.data(), 0, 1000);
2359 ImGui::SliderFloat2(name.c_str(), radii.data(), 0, 1000);
2363 if (corner_symmetry) {
2364 radius_tl[1] = radius_tl[0];
2365 radius_tr[1] = radius_tr[0];
2366 radius_bl[1] = radius_bl[0];
2367 radius_br[1] = radius_br[0];
2370 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2372 ImGui::Combo(
"Style", &style_index, style_options,
2373 sizeof(style_options) /
sizeof(
char*));
2374 ImGui::SliderFloat2(
"Center", center, 0, 1000);
2375 ImGui::SliderFloat2(
"Size", size, 0, 1000);
2376 ImGui::Checkbox(
"Symmetry: Horizontal", &horizontal_symmetry);
2377 ImGui::Checkbox(
"Symmetry: Vertical", &vertical_symmetry);
2378 ImGui::Checkbox(
"Symmetry: Corners", &corner_symmetry);
2379 AddRadiusControl(radius_tl,
"Top",
"Left");
2380 if (!horizontal_symmetry) {
2381 AddRadiusControl(radius_tr,
"Top",
"Right");
2383 radius_tr = radius_tl;
2385 if (!vertical_symmetry) {
2386 AddRadiusControl(radius_bl,
"Bottom",
"Left");
2388 radius_bl = radius_tl;
2390 if (!horizontal_symmetry && !vertical_symmetry) {
2391 AddRadiusControl(radius_br,
"Bottom",
"Right");
2393 if (horizontal_symmetry) {
2394 radius_br = radius_bl;
2396 radius_br = radius_tr;
2404 .
top_left = {radius_tl[0], radius_tl[1]},
2405 .top_right = {radius_tr[0], radius_tr[1]},
2406 .bottom_left = {radius_bl[0], radius_bl[1]},
2407 .bottom_right = {radius_br[0], radius_br[1]},
2414 std::unique_ptr<Geometry> geom;
2415 if (style_index == 0) {
2416 geom = std::make_unique<RoundSuperellipseGeometry>(
2428 auto contents = std::make_shared<SolidColorContents>();
2430 contents->SetGeometry(geom.get());
2435 return entity.
Render(context, pass);
2438 ASSERT_TRUE(OpenPlaygroundHere(callback));
2444 auto result = contents.ApplyColorFilter([](
const Color& color) {
2447 ASSERT_TRUE(result);
2449 Color(0.424452, 0.828743, 0.79105, 0.9375));
2452 #define APPLY_COLOR_FILTER_GRADIENT_TEST(name) \
2453 TEST_P(EntityTest, name##GradientApplyColorFilter) { \
2454 auto contents = name##GradientContents(); \
2455 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.75)}); \
2456 auto result = contents.ApplyColorFilter([](const Color& color) { \
2457 return color.Blend(Color::LimeGreen().WithAlpha(0.75), \
2458 BlendMode::kScreen); \
2460 ASSERT_TRUE(result); \
2462 std::vector<Color> expected = {Color(0.433247, 0.879523, 0.825324, 0.75)}; \
2463 ASSERT_COLORS_NEAR(contents.GetColors(), expected); \
2473 for (
int i = 0; i < 10000; i++) {
2476 Path path = builder.TakePath();
2482 auto cmd_buffer = content_context.
GetContext()->CreateCommandBuffer();
2485 content_context.
GetContext()->GetResourceAllocator());
2489 auto pass = cmd_buffer->CreateRenderPass(render_target);
2492 geom->GetPositionBuffer(content_context, entity, *pass);
2498 Point* written_data =
reinterpret_cast<Point*
>(
2502 std::vector<Point> expected = {
2503 Point(1019.46, 1026.54),
2504 Point(1026.54, 1019.46),
2505 Point(1020.45, 1027.54),
2506 Point(1027.54, 1020.46),
2507 Point(1020.46, 1027.53)
2511 EXPECT_NEAR(point.
x, expected[0].x, 0.1);
2512 EXPECT_NEAR(point.
y, expected[0].y, 0.1);
2515 EXPECT_NEAR(point.
x, expected[1].x, 0.1);
2516 EXPECT_NEAR(point.
y, expected[1].y, 0.1);
2519 EXPECT_NEAR(point.
x, expected[2].x, 0.1);
2520 EXPECT_NEAR(point.
y, expected[2].y, 0.1);
2523 EXPECT_NEAR(point.
x, expected[3].x, 0.1);
2524 EXPECT_NEAR(point.
y, expected[3].y, 0.1);
2527 EXPECT_NEAR(point.
x, expected[4].x, 0.1);
2528 EXPECT_NEAR(point.
y, expected[4].y, 0.1);
2533 for (
int i = 0; i < 10000; i++) {
2536 Path path = builder.TakePath();
2542 GetContext()->GetIdleWaiter());
2545 auto vertex_buffer = tessellator.GenerateLineStrip(path, *host_buffer, 1.0);
2551 Point* written_data =
reinterpret_cast<Point*
>(
2552 (vertex_buffer.vertex_buffer.GetBuffer()->OnGetContents() +
2553 vertex_buffer.vertex_buffer.GetRange().offset));
2555 std::vector<Point> expected = {
2564 EXPECT_NEAR(point.
x, expected[0].x, 0.1);
2565 EXPECT_NEAR(point.
y, expected[0].y, 0.1);
2568 EXPECT_NEAR(point.
x, expected[1].x, 0.1);
2569 EXPECT_NEAR(point.
y, expected[1].y, 0.1);
2572 EXPECT_NEAR(point.
x, expected[2].x, 0.1);
2573 EXPECT_NEAR(point.
y, expected[2].y, 0.1);
2576 EXPECT_NEAR(point.
x, expected[3].x, 0.1);
2577 EXPECT_NEAR(point.
y, expected[3].y, 0.1);
2580 EXPECT_NEAR(point.
x, expected[4].x, 0.1);
2581 EXPECT_NEAR(point.
y, expected[4].y, 0.1);
static std::shared_ptr< ColorFilterContents > MakeColorMatrix(FilterInput::Ref input, const ColorMatrix &color_matrix)
static std::shared_ptr< ColorFilterContents > MakeSrgbToLinearFilter(FilterInput::Ref input)
static std::shared_ptr< ColorFilterContents > MakeLinearToSrgbFilter(FilterInput::Ref input)
static std::shared_ptr< ColorFilterContents > MakeBlend(BlendMode blend_mode, FilterInput::Vector inputs, std::optional< Color > foreground_color=std::nullopt)
the [inputs] are expected to be in the order of dst, src.
void SetGeometry(const Geometry *geometry)
Set the geometry that this contents will use to render.
void SetColors(std::vector< Color > colors)
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
PipelineRef GetSolidFillPipeline(ContentContextOptions opts) const
std::shared_ptr< Context > GetContext() const
virtual bool IsOpaque(const Matrix &transform) const
Whether this Contents only emits opaque source colors from the fragment stage. This value does not ac...
To do anything rendering related with Impeller, you need a context.
virtual std::shared_ptr< CommandBuffer > CreateCommandBuffer() const =0
Create a new command buffer. Command buffers can be used to encode graphics, blit,...
virtual std::shared_ptr< CommandQueue > GetCommandQueue() const =0
Return the graphics queue for submitting command buffers.
virtual std::shared_ptr< Allocator > GetResourceAllocator() const =0
Returns the allocator used to create textures and buffers on the device.
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
virtual uint8_t * OnGetContents() const =0
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
std::optional< Rect > GetCoverage() const
BlendMode GetBlendMode() const
void SetContents(std::shared_ptr< Contents > contents)
void SetBlendMode(BlendMode blend_mode)
bool Render(const ContentContext &renderer, RenderPass &parent_pass) const
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
static constexpr BlendMode kLastPipelineBlendMode
@ kNormal
Blurred inside and outside.
@ kOuter
Nothing inside, blurred outside.
@ kInner
Blurred inside, nothing outside.
@ kSolid
Solid inside, blurred outside.
static std::shared_ptr< FilterContents > MakeMorphology(FilterInput::Ref input, Radius radius_x, Radius radius_y, MorphType morph_type)
static std::shared_ptr< FilterContents > MakeBorderMaskBlur(FilterInput::Ref input, Sigma sigma_x, Sigma sigma_y, BlurStyle blur_style=BlurStyle::kNormal)
static std::shared_ptr< FilterContents > MakeGaussianBlur(const FilterInput::Ref &input, Sigma sigma_x, Sigma sigma_y, Entity::TileMode tile_mode=Entity::TileMode::kDecal, BlurStyle mask_blur_style=BlurStyle::kNormal, const Geometry *mask_geometry=nullptr)
static std::shared_ptr< FilterContents > MakeYUVToRGBFilter(std::shared_ptr< Texture > y_texture, std::shared_ptr< Texture > uv_texture, YUVColorSpace yuv_color_space)
static std::unique_ptr< Geometry > MakeStrokePath(const Path &path, Scalar stroke_width=0.0, Scalar miter_limit=4.0, Cap stroke_cap=Cap::kButt, Join stroke_join=Join::kMiter)
static std::unique_ptr< Geometry > MakeFillPath(const Path &path, std::optional< Rect > inner_rect=std::nullopt)
static std::unique_ptr< Geometry > MakeRect(const Rect &rect)
static std::unique_ptr< Geometry > MakeCover()
BufferView EmplaceUniform(const UniformType &uniform)
Emplace uniform data onto the host buffer. Ensure that backend specific uniform alignment requirement...
static std::shared_ptr< HostBuffer > Create(const std::shared_ptr< Allocator > &allocator, const std::shared_ptr< const IdleWaiter > &idle_waiter)
void SetTileMode(Entity::TileMode tile_mode)
void SetColors(std::vector< Color > colors)
bool IsOpaque(const Matrix &transform) const override
Whether this Contents only emits opaque source colors from the fragment stage. This value does not ac...
Path TakePath(FillType fill=FillType::kNonZero)
PathBuilder & LineTo(Point point, bool relative=false)
Insert a line from the current position to point.
PathBuilder & MoveTo(Point point, bool relative=false)
PathBuilder & AddRect(const Rect &rect)
PathBuilder & SetBounds(Rect bounds)
Set the bounding box that will be used by Path.GetBoundingBox in place of performing the computation.
PathBuilder & AddCubicCurve(const Point &p1, const Point &cp1, const Point &cp2, const Point &p2)
Move to point p1, then insert a cubic curve from p1 to p2 with control points cp1 and cp2.
PathBuilder & AddLine(const Point &p1, const Point &p2)
Move to point p1, then insert a line from p1 to p2.
PathBuilder & AddRoundSuperellipse(RoundSuperellipse rse)
PathBuilder & SetConvexity(Convexity value)
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
std::optional< Rect > GetBoundingBox() const
A geometry class specialized for Canvas::DrawPoints.
std::optional< Rect > GetCoverage(const Matrix &transform) const override
bool IsOpaque(const Matrix &transform) const override
Whether this Contents only emits opaque source colors from the fragment stage. This value does not ac...
void SetTileMode(Entity::TileMode tile_mode)
void SetColors(std::vector< Color > colors)
Render passes encode render commands directed as one specific render target into an underlying comman...
VertexShader_ VertexShader
FragmentShader_ FragmentShader
a wrapper around the impeller [Allocator] instance that can be used to provide caching of allocated r...
virtual RenderTarget CreateOffscreen(const Context &context, ISize size, int mip_count, std::string_view label="Offscreen", RenderTarget::AttachmentConfig color_attachment_config=RenderTarget::kDefaultColorAttachmentConfig, std::optional< RenderTarget::AttachmentConfig > stencil_attachment_config=RenderTarget::kDefaultStencilAttachmentConfig, const std::shared_ptr< Texture > &existing_color_texture=nullptr, const std::shared_ptr< Texture > &existing_depth_stencil_texture=nullptr)
static BufferView EmplaceVulkanUniform(const std::shared_ptr< const std::vector< uint8_t >> &input_data, HostBuffer &host_buffer, const RuntimeUniformDescription &uniform)
bool IsOpaque(const Matrix &transform) const override
Whether this Contents only emits opaque source colors from the fragment stage. This value does not ac...
void SetColor(Color color)
A geometry that is created from a stroked path object.
A utility that generates triangles of the specified fill type given a polyline. This happens on the C...
static Rational RoundScaledFontSize(Scalar scale)
static std::shared_ptr< TextureContents > MakeRect(Rect destination)
A common case factory that marks the texture contents as having a destination rectangle....
bool IsOpaque(const Matrix &transform) const override
Whether this Contents only emits opaque source colors from the fragment stage. This value does not ac...
void SetTexture(std::shared_ptr< Texture > texture)
VertexBuffer CreateVertexBuffer(HostBuffer &host_buffer) const
VertexBufferBuilder & AddVertices(std::initializer_list< VertexType_ > vertices)
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
Vector2 padding
The halo padding in source space.
#define ASSERT_RECT_NEAR(a, b)
#define ASSERT_COLOR_NEAR(a, b)
EntityPlayground EntityTest
Rect RectMakeCenterSize(Point center, Size size)
TEST_P(AiksTest, DrawAtlasNoColor)
APPLY_COLOR_FILTER_GRADIENT_TEST(Linear)
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
static Vector3 RGBToYUV(Vector3 rgb, YUVColorSpace yuv_color_space)
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures(Context *context, YUVColorSpace yuv_color_space)
@ kPoint
Draws a point at each input vertex.
Point DrawPlaygroundPoint(PlaygroundPoint &point)
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
constexpr RuntimeStageBackend PlaygroundBackendToRuntimeStageBackend(PlaygroundBackend backend)
LinePipeline::FragmentShader FS
LinePipeline::VertexShader VS
void MoveTo(PathBuilder *builder, Scalar x, Scalar y)
static constexpr size_t kPointArenaSize
The size of the point arena buffer stored on the tessellator.
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
ContentContextOptions OptionsFromPass(const RenderPass &pass)
void Close(PathBuilder *builder)
const DeviceBuffer * GetBuffer() const
static constexpr Color LimeGreen()
static constexpr Color MintCream()
static constexpr Color DeepPink()
static constexpr Color Black()
static constexpr Color CornflowerBlue()
static constexpr Color White()
constexpr Color WithAlpha(Scalar new_alpha) const
static constexpr Color WhiteTransparent()
static constexpr Color Coral()
static constexpr Color Red()
constexpr Color Premultiply() const
Color Blend(Color source, BlendMode blend_mode) const
Blends an unpremultiplied destination color into a given unpremultiplied source color to form a new u...
static constexpr Color Blue()
static constexpr Color Green()
PrimitiveType primitive_type
bool has_depth_stencil_attachments
constexpr uint64_t ToKey() const
@ kNormal
The geometry has no overlapping triangles.
VertexBuffer vertex_buffer
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeTranslation(const Vector3 &t)
constexpr bool IsIdentity() const
static Matrix MakeRotationY(Radians r)
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
static Matrix MakeRotationZ(Radians r)
static constexpr Matrix MakeScale(const Vector3 &s)
static Matrix MakeRotationX(Radians r)
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
static RoundSuperellipse MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
constexpr static TRect MakeSize(const TSize< U > &size)
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...