7#include "flutter/display_list/display_list.h"
8#include "flutter/display_list/dl_builder.h"
9#include "flutter/display_list/dl_op_flags.h"
10#include "flutter/display_list/dl_sampling_options.h"
11#include "flutter/display_list/skia/dl_sk_canvas.h"
12#include "flutter/display_list/skia/dl_sk_conversions.h"
13#include "flutter/display_list/skia/dl_sk_dispatcher.h"
14#include "flutter/display_list/testing/dl_test_snippets.h"
15#include "flutter/display_list/testing/dl_test_surface_provider.h"
16#include "flutter/display_list/utils/dl_comparable.h"
17#include "flutter/fml/file.h"
18#include "flutter/fml/math.h"
19#include "flutter/testing/display_list_testing.h"
20#include "flutter/testing/testing.h"
21#ifdef IMPELLER_SUPPORTS_RENDERING
22#include "flutter/impeller/typographer/backends/skia/text_frame_skia.h"
181 for (
int y = 0;
y <
width;
y += cbdim) {
182 for (
int x = 0;
x <
height;
x += cbdim) {
183 DlPaint& cellp = ((
x +
y) & 1) == 0 ? p0 : p1;
196 return std::make_shared<DlImageColorSource>(
image,
213 : warning_(warning) {}
216 if (warnings_sent_.find(
name) == warnings_sent_.end()) {
217 warnings_sent_.insert(
name);
223 std::string warning_;
224 std::set<std::string> warnings_sent_;
251 copy.bounds_pad_.offset(bounds_pad_x, bounds_pad_y);
257 copy.scale_.fX *= scale_x;
258 copy.scale_.fY *= scale_y;
265 copy.absolute_pad_.offset(absolute_pad_x, absolute_pad_y);
272 copy.clip_pad_.offset(absolute_pad_x, absolute_pad_y);
285 copy.clip_.setEmpty();
291 SkScalar outset_x = rect.width() * (scales.
fX - 1);
292 SkScalar outset_y = rect.height() * (scales.
fY - 1);
293 return rect.makeOutset(outset_x, outset_y);
297 int worst_bounds_pad_x,
298 int worst_bounds_pad_y)
const {
300 allowed.
outset(bounds_pad_.
fX, bounds_pad_.
fY);
301 allowed =
Scale(allowed, scale_);
302 allowed.
outset(absolute_pad_.
fX, absolute_pad_.
fY);
308 int pad_left = std::max(0, pix_bounds.
fLeft - rounded.
fLeft);
309 int pad_top = std::max(0, pix_bounds.
fTop - rounded.
fTop);
310 int pad_right = std::max(0, pix_bounds.
fRight - rounded.
fRight);
311 int pad_bottom = std::max(0, pix_bounds.
fBottom - rounded.
fBottom);
312 int allowed_pad_x = std::max(pad_left, pad_right);
313 int allowed_pad_y = std::max(pad_top, pad_bottom);
314 if (worst_bounds_pad_x > allowed_pad_x ||
315 worst_bounds_pad_y > allowed_pad_y) {
317 << allowed_pad_x <<
", " << allowed_pad_y;
319 return (worst_bounds_pad_x > allowed_pad_x ||
320 worst_bounds_pad_y > allowed_pad_y);
326 return bounds_pad_ == other.bounds_pad_ && scale_ == other.scale_ &&
327 absolute_pad_ == other.absolute_pad_ && clip_ == other.clip_ &&
328 clip_pad_ == other.clip_pad_ &&
329 discrete_offset_ == other.discrete_offset_;
335 SkPoint absolute_pad_ = {0, 0};
336 SkRect clip_ = {-1E9, -1E9, 1E9, 1E9};
342template <
typename C,
typename P,
typename I>
374 virtual const uint32_t*
addr32(
int x,
int y)
const = 0;
381 bool take_snapshot =
false) {
384 addr_ = malloc(
info.computeMinByteSize() *
info.height());
386 surface->readPixels(pixmap_, 0, 0);
388 image_ =
surface->makeImageSnapshot();
396 const uint32_t*
addr32(
int x,
int y)
const override {
409 void* addr_ =
nullptr;
420 int width()
const override {
return screenshot_->width(); };
421 int height()
const override {
return screenshot_->height(); }
422 const uint32_t*
addr32(
int x,
int y)
const override {
423 return screenshot_->addr32(
x,
y);
426 screenshot_->write(
path);
471 : sk_setup_(sk_setup),
472 sk_render_(sk_render),
473 sk_restore_(sk_restore),
474 sk_image_(sk_image) {}
479 sk_setup_({canvas,
paint, sk_image_});
480 setup_paint_ =
paint;
484 sk_render_({canvas,
paint, sk_image_});
485 sk_restore_({canvas,
paint, sk_image_});
514 : dl_setup_(dl_setup),
515 dl_render_(dl_render),
516 dl_restore_(dl_restore),
517 dl_image_(dl_image) {}
527 dl_setup_({canvas,
paint, dl_image_});
528 setup_paint_ =
paint;
532 dl_render_({canvas,
paint, dl_image_});
533 dl_restore_({canvas,
paint, dl_image_});
539 return builder.Build();
548 return dl_image_->impeller_texture() !=
nullptr;
561 : picture_(
std::move(picture)) {}
574 : display_list_(
std::move(display_list)) {}
623 test_impeller_image_ = makeTestImpellerImage(provider_);
625 test_impeller_image_);
634 auto canvas =
surface->getCanvas();
637 int restore_count = canvas->save();
638 canvas->scale(
info.scale,
info.scale);
639 renderer.Render(canvas,
info);
640 canvas->restoreToCount(restore_count);
646 return std::make_unique<SkRenderResult>(
surface);
661 builder.Clear(
info.bg);
662 auto render_dl = renderer.MakeDisplayList(
info);
663 builder.DrawDisplayList(render_dl);
664 auto dl = builder.Build();
666 return std::make_unique<ImpellerRenderResult>(std::move(snap),
667 render_dl->bounds());
682 return ref_impeller_result_.get();
695 return surface_1x_->sk_surface();
698 return surface_2x_->sk_surface();
701 <<
") not supported.";
706 const DlSurfaceProvider* provider_;
707 const PixelFormat format_;
708 std::shared_ptr<DlSurfaceInstance> surface_1x_;
709 std::shared_ptr<DlSurfaceInstance> surface_2x_;
711 DlPaint ref_dl_paint_;
714 std::unique_ptr<RenderResult> ref_sk_result_;
715 std::unique_ptr<RenderResult> ref_dl_result_;
716 std::unique_ptr<ImpellerRenderResult> ref_impeller_result_;
725 return surface->makeImageSnapshot();
728 const DlSurfaceProvider*
provider) {
737const sk_sp<SkImage> RenderEnvironment::kTestSkImage = makeTestSkImage();
781 bg_, has_diff_clip_, mutating_layer,
786 return CaseParameters(info_, sk_setup_, dl_setup_, sk_restore_, dl_restore_,
787 bg, has_diff_clip_, has_mutating_save_layer_,
788 fuzzy_compare_components_);
792 return CaseParameters(info_, sk_setup_, dl_setup_, sk_restore_, dl_restore_,
793 bg_,
true, has_mutating_save_layer_,
794 fuzzy_compare_components_);
797 std::string
info()
const {
return info_; }
809 const std::string info_;
815 const bool has_diff_clip_;
816 const bool has_mutating_save_layer_;
817 const bool fuzzy_compare_components_;
842 if (
paint.getColorSourcePtr() && !
paint.getColorSourcePtr()->asColor()) {
860 if (
env.ref_clip_bounds() != renderer.setup_clip_bounds() ||
864 if (
env.ref_matrix() != renderer.setup_matrix() && !flags_.
is_flood()) {
873 if (renderer.targets_impeller()) {
914 if (renderer.targets_impeller()) {
935 getCap(ref_attr, geo_flags) !=
getCap(attr, geo_flags)) {
947 ref_miter < 1.4 || test_miter < 1.4) {
948 if (ref_miter != test_miter) {
985 paint.getStrokeMiter() *
paint.getStrokeWidth() * 0.5f;
1008 auto path_effect =
paint.getPathEffect();
1032 h_tolerance = v_tolerance =
adjust;
1036 return new_tolerance;
1057 is_draw_text_blob_ =
true;
1061 is_draw_display_list_ =
true;
1065 is_draw_line_ =
true;
1069 is_draw_arc_center_ =
true;
1073 is_draw_path_ =
true;
1077 ignores_dashes_ =
true;
1081 is_horizontal_line_ =
true;
1085 is_vertical_line_ =
true;
1095 bool is_draw_text_blob_ =
false;
1096 bool is_draw_display_list_ =
false;
1097 bool is_draw_line_ =
false;
1098 bool is_draw_arc_center_ =
false;
1099 bool is_draw_path_ =
false;
1100 bool ignores_dashes_ =
false;
1101 bool is_horizontal_line_ =
false;
1102 bool is_vertical_line_ =
false;
1114 if (provider ==
nullptr) {
1116 <<
" not supported (ignoring)";
1120 PixelFormat::kN32PremulPixelFormat);
1143 if (
env.supports_impeller()) {
1144 auto impeller_result =
env.ref_impeller_result();
1145 if (!
checkPixels(impeller_result, impeller_result->render_bounds(),
1146 "Impeller reference")) {
1147 std::string test_name =
1148 ::testing::UnitTest::GetInstance()->current_test_info()->name();
1149 save_to_png(impeller_result, test_name +
" (Impeller reference)",
1150 "base rendering was blank or out of bounds");
1154 warnings.
warn(
env.backend_name());
1161 if (
params.uses_paint()) {
1177 ctx.canvas->restore();
1186 ctx.canvas->DrawRect(
1189 ctx.canvas->Restore();
1193 ctx.canvas->restore();
1197 ctx.canvas->Restore();
1202 "With prior save/clip/restore",
1207 ctx.
canvas->drawRect(rect, p2);
1209 ctx.
canvas->drawRect(rect, p2);
1214 ctx.
canvas->ClipRect(
clip, ClipOp::kIntersect,
false);
1216 ctx.
canvas->DrawRect(rect, p2);
1218 ctx.
canvas->DrawRect(rect, p2);
1223 "saveLayer no paint, no bounds",
1225 ctx.
canvas->saveLayer(
nullptr,
nullptr);
1228 ctx.
canvas->SaveLayer(
nullptr,
nullptr);
1230 .with_restore(sk_safe_restore, dl_safe_restore,
false));
1233 "saveLayer no paint, with bounds",
1235 ctx.
canvas->saveLayer(layer_bounds,
nullptr);
1238 ctx.
canvas->SaveLayer(&layer_bounds,
nullptr);
1240 .with_restore(sk_safe_restore, dl_safe_restore,
true));
1243 "saveLayer with alpha, no bounds",
1247 ctx.
canvas->saveLayer(
nullptr, &save_p);
1251 save_p.
setColor(alpha_layer_color);
1252 ctx.
canvas->SaveLayer(
nullptr, &save_p);
1254 .with_restore(sk_safe_restore, dl_safe_restore,
true));
1257 "saveLayer with peephole alpha, no bounds",
1261 ctx.
canvas->saveLayer(
nullptr, &save_p);
1265 save_p.
setColor(alpha_layer_color);
1266 ctx.
canvas->SaveLayer(
nullptr, &save_p);
1268 .with_restore(sk_opt_restore, dl_opt_restore,
true,
true));
1271 "saveLayer with alpha and bounds",
1275 ctx.
canvas->saveLayer(layer_bounds, &save_p);
1279 save_p.
setColor(alpha_layer_color);
1280 ctx.
canvas->SaveLayer(&layer_bounds, &save_p);
1282 .with_restore(sk_safe_restore, dl_safe_restore,
true));
1296 ctx.
canvas->drawPaint(setup_p);
1301 ctx.
canvas->DrawPaint(setup_p);
1304 ctx.
paint.setAlpha(ctx.
paint.getAlpha() / 2);
1307 ctx.
paint.setAlpha(ctx.
paint.getAlpha() / 2);
1319 "saveLayer with backdrop",
1321 sk_backdrop_setup(ctx);
1323 nullptr,
nullptr, sk_backdrop.get(), 0));
1324 sk_content_setup(ctx);
1327 dl_backdrop_setup(ctx);
1328 ctx.
canvas->SaveLayer(
nullptr,
nullptr, &dl_backdrop);
1329 dl_content_setup(ctx);
1331 .with_restore(sk_safe_restore, dl_safe_restore,
true));
1334 "saveLayer with bounds and backdrop",
1336 sk_backdrop_setup(ctx);
1338 &layer_bounds,
nullptr, sk_backdrop.get(), 0));
1339 sk_content_setup(ctx);
1342 dl_backdrop_setup(ctx);
1343 ctx.
canvas->SaveLayer(&layer_bounds,
nullptr,
1345 dl_content_setup(ctx);
1347 .with_restore(sk_safe_restore, dl_safe_restore,
true));
1350 "clipped saveLayer with backdrop",
1352 sk_backdrop_setup(ctx);
1353 ctx.
canvas->clipRect(layer_bounds);
1355 nullptr,
nullptr, sk_backdrop.get(), 0));
1356 sk_content_setup(ctx);
1359 dl_backdrop_setup(ctx);
1360 ctx.
canvas->ClipRect(layer_bounds);
1361 ctx.
canvas->SaveLayer(
nullptr,
nullptr, &dl_backdrop);
1362 dl_content_setup(ctx);
1364 .with_restore(sk_safe_restore, dl_safe_restore,
true));
1369 constexpr float rotate_alpha_color_matrix[20] = {
1377 auto sk_alpha_rotate_filter =
1382 "saveLayer ColorFilter, no bounds",
1386 ctx.
canvas->saveLayer(
nullptr, &save_p);
1387 ctx.
paint.setStrokeWidth(5.0);
1392 ctx.
canvas->SaveLayer(
nullptr, &save_p);
1393 ctx.
paint.setStrokeWidth(5.0);
1395 .with_restore(sk_safe_restore, dl_safe_restore,
true));
1400 "saveLayer ColorFilter and bounds",
1405 ctx.
paint.setStrokeWidth(5.0);
1411 ctx.
paint.setStrokeWidth(5.0);
1413 .with_restore(sk_safe_restore, dl_safe_restore,
true));
1419 constexpr float color_matrix[20] = {
1433 "saveLayer ImageFilter, no bounds",
1437 ctx.
canvas->saveLayer(
nullptr, &save_p);
1438 ctx.
paint.setStrokeWidth(5.0);
1443 ctx.
canvas->SaveLayer(
nullptr, &save_p);
1444 ctx.
paint.setStrokeWidth(5.0);
1446 .with_restore(sk_safe_restore, dl_safe_restore,
true));
1451 "saveLayer ImageFilter and bounds",
1456 ctx.
paint.setStrokeWidth(5.0);
1462 ctx.
paint.setStrokeWidth(5.0);
1464 .with_restore(sk_safe_restore, dl_safe_restore,
true));
1482 ctx.
canvas->translate(0.1, 0.1);
1483 ctx.
paint.setAntiAlias(is_aa);
1484 ctx.
paint.setStrokeWidth(5.0);
1487 ctx.
canvas->Translate(0.1, 0.1);
1488 ctx.
paint.setAntiAlias(is_aa);
1489 ctx.
paint.setStrokeWidth(5.0);
1498 testP, aa_env, aa_tolerance,
1500 "AntiAlias == True",
1504 testP, aa_env, aa_tolerance,
1506 "AntiAlias == False",
1512 testP,
env, tolerance,
1522 testP,
env, tolerance,
1544 ctx.
paint.setColor(blendable_color.
argb());
1548 ctx.
paint.setColor(blendable_color);
1556 ctx.
paint.setColor(blendable_color.
argb());
1560 ctx.
paint.setColor(blendable_color);
1572 ctx.
paint.setStrokeWidth(5.0);
1576 ctx.
paint.setStrokeWidth(5.0);
1583 auto sk_filter_decal_5 =
1587 RenderWith(testP, blur_env, blur_5_tolerance,
1589 "ImageFilter == Decal Blur 5",
1592 ctx.
paint.setImageFilter(sk_filter_decal_5);
1596 ctx.
paint.setImageFilter(&dl_filter_decal_5);
1600 auto sk_filter_clamp_5 =
1603 RenderWith(testP, blur_env, blur_5_tolerance,
1605 "ImageFilter == Clamp Blur 5",
1608 ctx.
paint.setImageFilter(sk_filter_clamp_5);
1612 ctx.
paint.setImageFilter(&dl_filter_clamp_5);
1624 ctx.
paint.setStrokeWidth(5.0);
1628 ctx.
paint.setStrokeWidth(5.0);
1638 "ImageFilter == Dilate 5",
1640 sk_dilate_setup(ctx);
1641 ctx.
paint.setImageFilter(sk_dilate_filter_5);
1644 dl_dilate_setup(ctx);
1645 ctx.
paint.setImageFilter(&dl_dilate_filter_5);
1656 ctx.
paint.setStrokeWidth(6.0);
1660 ctx.
paint.setStrokeWidth(6.0);
1672 "ImageFilter == Erode 1",
1674 sk_erode_setup(ctx);
1675 ctx.
paint.setImageFilter(sk_erode_filter_1);
1678 dl_erode_setup(ctx);
1679 ctx.
paint.setImageFilter(&dl_erode_filter_1);
1685 constexpr float rotate_color_matrix[20] = {
1691 constexpr float invert_color_matrix[20] = {
1695 1.0, 1.0, 1.0, 1.0, 0,
1704 "ColorFilter == RotateRGB",
1707 ctx.
paint.setColorFilter(sk_color_filter);
1711 ctx.
paint.setColorFilter(&dl_color_filter);
1719 "ColorFilter == Invert",
1722 ctx.
paint.setColorFilter(
1727 ctx.
paint.setInvertColors(
true);
1741 "MaskFilter == Blur 5",
1743 ctx.
paint.setStrokeWidth(5.0);
1744 ctx.
paint.setMaskFilter(sk_mask_filter);
1747 ctx.
paint.setStrokeWidth(5.0);
1748 ctx.
paint.setMaskFilter(&dl_mask_filter);
1781 "LinearGradient GYB",
1783 ctx.
paint.setShader(sk_gradient);
1787 ctx.
paint.setColorSource(dl_gradient);
1818 env.provider()->backend_type() != BackendType::kSoftwareBackend;
1821 "Stroke + defaults",
1824 ctx.
paint.setStrokeWidth(1.0);
1830 ctx.
paint.setStrokeWidth(1.0);
1837 "Fill + unnecessary StrokeWidth 10",
1840 ctx.
paint.setStrokeWidth(10.0);
1844 ctx.
paint.setStrokeWidth(10.0);
1851 ctx.
paint.setStrokeWidth(5.0);
1855 ctx.
paint.setStrokeWidth(5.0);
1862 RenderWith(testP, stroke_base_env, tolerance,
1867 ctx.
paint.setStrokeWidth(10.0);
1871 ctx.
paint.setStrokeWidth(10.0);
1873 RenderWith(testP, stroke_base_env, tolerance,
1878 ctx.
paint.setStrokeWidth(5.0);
1882 ctx.
paint.setStrokeWidth(5.0);
1885 RenderWith(testP, stroke_base_env, tolerance,
1887 "Stroke Width 5, Square Cap",
1890 ctx.
paint.setStrokeWidth(5.0);
1895 ctx.
paint.setStrokeWidth(5.0);
1898 RenderWith(testP, stroke_base_env, tolerance,
1900 "Stroke Width 5, Round Cap",
1903 ctx.
paint.setStrokeWidth(5.0);
1908 ctx.
paint.setStrokeWidth(5.0);
1912 RenderWith(testP, stroke_base_env, tolerance,
1914 "Stroke Width 5, Bevel Join",
1917 ctx.
paint.setStrokeWidth(5.0);
1922 ctx.
paint.setStrokeWidth(5.0);
1925 RenderWith(testP, stroke_base_env, tolerance,
1927 "Stroke Width 5, Round Join",
1930 ctx.
paint.setStrokeWidth(5.0);
1935 ctx.
paint.setStrokeWidth(5.0);
1939 RenderWith(testP, stroke_base_env, tolerance,
1941 "Stroke Width 5, Miter 10",
1944 ctx.
paint.setStrokeWidth(5.0);
1945 ctx.
paint.setStrokeMiter(10.0);
1950 ctx.
paint.setStrokeWidth(5.0);
1951 ctx.
paint.setStrokeMiter(10.0);
1955 RenderWith(testP, stroke_base_env, tolerance,
1957 "Stroke Width 5, Miter 0",
1960 ctx.
paint.setStrokeWidth(5.0);
1961 ctx.
paint.setStrokeMiter(0.0);
1966 ctx.
paint.setStrokeWidth(5.0);
1967 ctx.
paint.setStrokeMiter(0.0);
1972 const SkScalar test_dashes_1[] = {29.0, 2.0};
1973 const SkScalar test_dashes_2[] = {17.0, 1.5};
1977 RenderWith(testP, stroke_base_env, tolerance,
1979 "PathEffect without forced stroking == Dash-29-2",
1982 ctx.
paint.setStrokeWidth(5.0);
1983 ctx.
paint.setPathEffect(sk_dash_effect);
1987 ctx.
paint.setStrokeWidth(5.0);
1988 ctx.
paint.setPathEffect(dl_dash_effect);
1992 RenderWith(testP, stroke_base_env, tolerance,
1994 "PathEffect == Dash-29-2",
1999 ctx.
paint.setStrokeWidth(5.0);
2000 ctx.
paint.setPathEffect(sk_dash_effect);
2006 ctx.
paint.setStrokeWidth(5.0);
2007 ctx.
paint.setPathEffect(dl_dash_effect);
2013 RenderWith(testP, stroke_base_env, tolerance,
2015 "PathEffect == Dash-17-1.5",
2020 ctx.
paint.setStrokeWidth(5.0);
2021 ctx.
paint.setPathEffect(sk_dash_effect);
2027 ctx.
paint.setStrokeWidth(5.0);
2028 ctx.
paint.setPathEffect(dl_dash_effect);
2042 testP,
env, tolerance,
2048 testP,
env, tolerance,
2054 testP,
env, skewed_tolerance,
2060 testP,
env, skewed_tolerance,
2075 tweak, 1.0 + tweak, 10,
2078 testP,
env, skewed_tolerance,
2080 "Transform 2D Affine",
2095 testP,
env, skewed_tolerance,
2097 "Transform Full Perspective",
2119 "Hard ClipRect inset by 15.4",
2124 ctx.
canvas->ClipRect(r_clip, ClipOp::kIntersect,
false);
2128 "AntiAlias ClipRect inset by 15.4",
2133 ctx.
canvas->ClipRect(r_clip, ClipOp::kIntersect,
true);
2137 "Hard ClipRect Diff, inset by 15.4",
2142 ctx.
canvas->ClipRect(r_clip, ClipOp::kDifference,
false);
2153 "Hard ClipRRect with radius of 15.4",
2159 ctx.
canvas->ClipRRect(rr_clip, ClipOp::kIntersect,
false);
2163 "AntiAlias ClipRRect with radius of 15.4",
2168 ctx.
canvas->ClipRRect(rr_clip, ClipOp::kIntersect,
true);
2172 "Hard ClipRRect Diff, with radius of 15.4",
2178 ctx.
canvas->ClipRRect(rr_clip, ClipOp::kDifference,
false);
2183 path_clip.addRect(r_clip);
2187 "Hard ClipPath inset by 15.4",
2193 ctx.
canvas->ClipPath(path_clip, ClipOp::kIntersect,
false);
2197 "AntiAlias ClipPath inset by 15.4",
2203 ctx.
canvas->ClipPath(path_clip, ClipOp::kIntersect,
true);
2206 testP,
env, diff_tolerance,
2208 "Hard ClipPath Diff, inset by 15.4",
2213 ctx.
canvas->ClipPath(path_clip, ClipOp::kDifference,
false);
2227 if (ret.is_valid()) {
2232 if (ret.is_valid()) {
2236 <<
") for impeller failure images" <<
", ret = " << ret.get()
2237 <<
", errno = " << errno;
2242 std::string base_dir =
"./impeller_failure_images";
2246 for (
int i = 0; i < 10000; i++) {
2247 std::string sub_dir = std::to_string(i);
2248 while (sub_dir.length() < 4) {
2249 sub_dir =
"0" + sub_dir;
2251 std::string try_dir = base_dir +
"/" + sub_dir;
2262 FML_LOG(
ERROR) <<
"Too many output directories for Impeller failure images";
2266 const std::string& op_desc,
2267 const std::string& reason) {
2280 for (
const char& ch : op_desc) {
2281 filename += (ch ==
':' || ch ==
' ') ?
'_' : ch;
2283 filename = filename +
".png";
2293 std::string test_name =
2294 ::testing::UnitTest::GetInstance()->current_test_info()->name();
2295 const std::string
info =
2296 env.backend_name() +
": " + test_name +
" (" + caseP.
info() +
")";
2308 auto sk_result =
env.getResult(base_info, sk_job);
2314 auto dl_result =
env.getResult(base_info, dl_job);
2328 SkRect sk_bounds = sk_picture->cullRect();
2329 checkPixels(sk_result.get(), sk_bounds,
info +
" (Skia reference)", bg);
2333 info +
" (attribute should not have effect)");
2336 info +
" (attribute should affect rendering)");
2343 if (
env.supports_impeller() &&
2349 env.impeller_image());
2350 auto imp_result =
env.getImpellerResult(base_info, imp_job);
2351 std::string imp_info =
info +
" (Impeller)";
2352 bool success =
checkPixels(imp_result.get(), imp_result->render_bounds(),
2355 success = success &&
2357 env.ref_impeller_result(), imp_result.get(),
true,
2358 imp_info +
" (attribute should not have effect)");
2360 success = success &&
2362 env.ref_impeller_result(), imp_result.get(),
false,
2363 imp_info +
" (attribute should affect rendering)");
2371 "compare to reference without attributes");
2373 "and to Skia reference with attributes");
2375 "and to Skia reference without attributes");
2380 info +
" (DlCanvas output matches SkCanvas)");
2383 SkRect dl_bounds = display_list->bounds();
2384 if (!sk_bounds.
roundOut().contains(dl_bounds)) {
2387 << sk_bounds.
fLeft <<
", " << sk_bounds.
fTop <<
" => "
2390 << dl_bounds.
fLeft <<
", " << dl_bounds.
fTop <<
" => "
2392 if (!dl_bounds.
contains(sk_bounds)) {
2397 FML_LOG(
ERROR) <<
"###### DisplayList bounds larger than reference!";
2413 EXPECT_EQ(
static_cast<int>(display_list->op_count()),
2414 sk_picture->approximateOpCount())
2416 EXPECT_EQ(
static_cast<int>(display_list->op_count()),
2417 sk_picture->approximateOpCount())
2422 auto dl_builder_result =
env.getResult(base_info, dl_builder_job);
2425 dl_builder_result.get(), dl_result.get(),
2426 info +
" (DlCanvas DL output close to Builder Dl output)",
2427 &dl_bounds, &tolerance, bg,
true);
2430 dl_builder_result.get(), dl_result.get(),
true,
2431 info +
" (DlCanvas DL output matches Builder Dl output)");
2435 info +
" (DisplayList built directly -> surface)",
2436 &dl_bounds, &tolerance, bg,
2439 if (display_list->can_apply_group_opacity()) {
2441 info +
" with Group Opacity", bg);
2457 .
width = test_width_2,
2458 .height = test_height_2,
2462 auto ref_x2_result =
env.getResult(info_2x, sk_job_x2);
2463 ASSERT_EQ(ref_x2_result->width(), test_width_2) <<
info;
2464 ASSERT_EQ(ref_x2_result->height(), test_height_2) <<
info;
2467 auto test_x2_result =
env.getResult(info_2x, dl_job_x2);
2469 info +
" (Both rendered scaled 2x)",
nullptr,
nullptr,
2471 test_width_2, test_height_2,
false);
2476 for (
int i = 0; i < 32; i += 8) {
2477 int comp_a = (pixel_a >> i) & 0xff;
2478 int comp_b = (pixel_b >> i) & 0xff;
2479 if (std::abs(comp_a - comp_b) > fudge) {
2487 if (
env.format() == PixelFormat::k565PixelFormat) {
2490 if (
env.provider()->backend_type() == BackendType::kOpenGlBackend) {
2500 const std::string&
info,
2509 auto group_opacity_result =
env.getResult(opacity_info, opacity_job);
2517 int pixels_touched = 0;
2518 int pixels_different = 0;
2530 const uint32_t* ref_row = ref_result->
addr32(0,
y);
2531 const uint32_t* test_row = group_opacity_result->addr32(0,
y);
2533 uint32_t ref_pixel = ref_row[
x];
2534 uint32_t test_pixel = test_row[
x];
2535 if (ref_pixel != bg.
argb() || test_pixel != bg.
argb()) {
2537 for (
int i = 0; i < 32; i += 8) {
2538 int ref_comp = (ref_pixel >> i) & 0xff;
2539 int bg_comp = (bg.
argb() >> i) & 0xff;
2540 SkScalar faded_comp = bg_comp + (ref_comp - bg_comp) * opacity;
2541 int test_comp = (test_pixel >> i) & 0xff;
2542 if (std::abs(faded_comp - test_comp) > fudge) {
2543 int diff = std::abs(faded_comp - test_comp);
2544 if (max_diff < diff) {
2554 ASSERT_GT(pixels_touched, 20) <<
info;
2555 if (pixels_different > 1) {
2558 ASSERT_LE(pixels_different, 1) <<
info;
2563 const std::string&
info,
2565 uint32_t untouched = bg.premultipliedArgb();
2566 int pixels_touched = 0;
2572 const uint32_t* ref_row = ref_result->
addr32(0,
y);
2574 if (ref_row[
x] != untouched) {
2582 EXPECT_EQ(pixels_oob, 0) <<
info;
2583 EXPECT_GT(pixels_touched, 0) <<
info;
2584 return pixels_oob == 0 && pixels_touched > 0;
2591 const uint32_t* ref_row = ref_result->
addr32(0,
y);
2592 const uint32_t* test_row = test_result->
addr32(0,
y);
2594 if (ref_row[
x] != test_row[
x]) {
2595 if (ref_row[
x] == 0) {
2605 const std::string&
info) {
2607 info +
" reference rendering");
2613 const std::string&
info) {
2614 int w = test_result->
width();
2615 int h = test_result->
height();
2618 int pixels_different = 0;
2619 for (
int y = 0;
y <
h;
y++) {
2620 const uint32_t* ref_row = ref_result->
addr32(0,
y);
2621 const uint32_t* test_row = test_result->
addr32(0,
y);
2622 for (
int x = 0;
x <
w;
x++) {
2623 if (ref_row[
x] != test_row[
x]) {
2624 if (should_match && pixels_different < 5) {
2625 FML_LOG(
ERROR) << std::hex << ref_row[
x] <<
" != " << test_row[
x];
2632 EXPECT_EQ(pixels_different, 0) <<
info;
2633 return pixels_different == 0;
2635 EXPECT_NE(pixels_different, 0) <<
info;
2636 return pixels_different != 0;
2642 const std::string&
info,
2646 bool fuzzyCompares =
false,
2649 bool printMismatches =
false) {
2656 int pixels_different = 0;
2663 const uint32_t* ref_row = ref_result->
addr32(0,
y);
2664 const uint32_t* test_row = test_result->
addr32(0,
y);
2666 if (bounds && test_row[
x] != untouched) {
2684 : test_row[
x] == ref_row[
x];
2686 if (printMismatches && pixels_different < 5) {
2688 <<
"] mismatch: " << std::hex << test_row[
x]
2689 <<
"(test) != (ref)" << ref_row[
x] << std::dec;
2695 if (pixels_oob > 0) {
2697 << min_x <<
", " << min_y <<
" => " << max_x <<
", "
2700 << bounds->fLeft <<
", " << bounds->fTop
2702 << bounds->fRight <<
", " << bounds->fBottom
2704 }
else if (bounds) {
2707 ASSERT_EQ(pixels_oob, 0) <<
info;
2708 ASSERT_EQ(pixels_different, 0) <<
info;
2718 int pad_left = std::max(0, pixLeft - bounds.fLeft);
2719 int pad_top = std::max(0, pixTop - bounds.fTop);
2720 int pad_right = std::max(0, bounds.fRight - pixRight);
2721 int pad_bottom = std::max(0, bounds.fBottom - pixBottom);
2725 int pix_width = pix_size.
width();
2726 int pix_height = pix_size.
height();
2727 int worst_pad_x = std::max(pad_left, pad_right);
2728 int worst_pad_y = std::max(pad_top, pad_bottom);
2729 if (tolerance->
overflows(pix_bounds, worst_pad_x, worst_pad_y)) {
2732 << pixLeft <<
", " << pixTop <<
" => "
2733 << pixRight <<
", " << pixBottom
2736 << bounds.fLeft <<
", " << bounds.fTop
2738 << bounds.fRight <<
", " << bounds.fBottom
2740 FML_LOG(
ERROR) <<
"Bounds overly conservative by up to "
2741 << worst_pad_x <<
", " << worst_pad_y
2742 <<
" (" << (worst_pad_x * 100.0 / pix_width)
2743 <<
"%, " << (worst_pad_y * 100.0 / pix_height) <<
"%)";
2744 int pix_area = pix_size.
area();
2745 int dl_area = bounds.width() * bounds.height();
2746 FML_LOG(
ERROR) <<
"Total overflow area: " << (dl_area - pix_area)
2747 <<
" (+" << (dl_area * 100.0 / pix_area - 100.0)
2758 FML_CHECK(face->countGlyphs() > 0) <<
"No glyphs in font";
2775template <
typename BaseT>
2782 if (prefix.length() > str.length()) {
2785 for (
size_t i = 0; i < prefix.length(); i++) {
2786 if (str[i] != prefix[i]) {
2794 bool do_software =
true;
2795 bool do_opengl =
false;
2796 bool do_metal =
false;
2797 std::vector<std::string>
args = ::testing::internal::GetArgvs();
2798 for (
auto p_arg = std::next(
args.begin()); p_arg !=
args.end(); p_arg++) {
2799 std::string arg = *p_arg;
2801 if (arg ==
"--save-impeller-failures") {
2807 arg =
"-" + arg.substr(4);
2809 if (arg ==
"--enable-software") {
2810 do_software = enable;
2811 }
else if (arg ==
"--enable-opengl" || arg ==
"--enable-gl") {
2813 }
else if (arg ==
"--enable-metal") {
2826 std::string providers =
"";
2830 FML_LOG(INFO) <<
"Running tests on [" << providers <<
" ]";
2837 <<
" images saved in "
2840 FML_LOG(INFO) <<
" " << filename;
2893 ctx.
canvas->drawColor(0x7FFF00FF);
2921 ctx.
canvas->drawLine(p1, p2, p);
2922 ctx.
canvas->drawLine(p3, p4, p);
2923 ctx.
canvas->drawLine(p5, p6, p);
2924 ctx.
canvas->drawLine(p7, p8, p);
2948 ctx.
canvas->drawLine(p1, p2, p);
2970 ctx.
canvas->drawLine(p1, p2, p);
3094 kDrawArcNoCenterFlags));
3116 kDrawArcWithCenterFlags)
3117 .set_draw_arc_center());
3142 {x0, y0}, {x1, y0}, {x2, y0}, {x3, y0}, {x4, y0}, {x5, y0}, {x6, y0},
3143 {x0, y1}, {x1, y1}, {x2, y1}, {x3, y1}, {x4, y1}, {x5, y1}, {x6, y1},
3144 {x0, y2}, {x1, y2}, {x2, y2}, {x3, y2}, {x4, y2}, {x5, y2}, {x6, y2},
3145 {x0, y3}, {x1, y3}, {x2, y3}, {x3, y3}, {x4, y3}, {x5, y3}, {x6, y3},
3146 {x0, y4}, {x1, y4}, {x2, y4}, {x3, y4}, {x4, y4}, {x5, y4}, {x6, y4},
3147 {x0, y5}, {x1, y5}, {x2, y5}, {x3, y5}, {x4, y5}, {x5, y5}, {x6, y5},
3148 {x0, y6}, {x1, y6}, {x2, y6}, {x3, y6}, {x4, y6}, {x5, y6}, {x6, y6},
3165 auto mode = PointMode::kPoints;
3168 kDrawPointsAsPointsFlags)
3193 {x0, y0}, {x3, y3}, {x3, y0}, {x0, y3},
3204 ASSERT_TRUE((
count & 1) == 0);
3217 auto mode = PointMode::kLines;
3220 kDrawPointsAsLinesFlags));
3236 const int count1 =
sizeof(points1) /
sizeof(points1[0]);
3247 ctx.
canvas->drawPoints(
mode, count1, points1, p);
3250 auto mode = PointMode::kPolygon;
3253 kDrawPointsAsPolygonFlags));
3276 const DlColor dl_colors[6] = {
3280 const SkColor sk_colors[6] = {
3284 const std::shared_ptr<DlVertices> dl_vertices =
3286 const auto sk_vertices =
3288 pts,
nullptr, sk_colors);
3300 kDrawVerticesFlags));
3331 const std::shared_ptr<DlVertices> dl_vertices =
3341 v_paint.setShader(MakeColorSource(ctx.image));
3354 kDrawVerticesFlags));
3371 kDrawImageWithPaintFlags));
3401 kDrawImageWithPaintFlags));
3410 ctx.
canvas->drawImageRect(
3415 ctx.
canvas->DrawImageRect(
3419 kDrawImageRectWithPaintFlags));
3428 ctx.
canvas->drawImageRect(
3433 ctx.
canvas->DrawImageRect(
3437 kDrawImageRectFlags));
3446 ctx.
canvas->drawImageRect(
3451 ctx.
canvas->DrawImageRect(
3455 kDrawImageRectWithPaintFlags));
3464 ctx.
canvas->drawImageNine(ctx.
image.get(), src, dst,
3471 kDrawImageNineWithPaintFlags));
3480 ctx.
canvas->drawImageNine(ctx.
image.get(), src, dst,
3487 kDrawImageNineFlags));
3496 ctx.
canvas->drawImageNine(ctx.
image.get(), src, dst,
3503 kDrawImageNineWithPaintFlags));
3540 ctx.
canvas->drawAtlas(ctx.
image.get(), xform, tex, sk_colors, 4,
3545 ctx.
canvas->DrawAtlas(ctx.
image, xform, tex, dl_colors, 4,
3549 kDrawAtlasWithPaintFlags));
3586 ctx.
canvas->drawAtlas(ctx.
image.get(), xform, tex, sk_colors, 4,
3591 ctx.
canvas->DrawAtlas(ctx.
image, xform, tex, dl_colors, 4,
3632 ctx.
canvas->drawAtlas(ctx.
image.get(), xform, tex, sk_colors, 2,
3634 nullptr, &ctx.
paint);
3637 ctx.
canvas->DrawAtlas(ctx.
image, xform, tex, dl_colors, 2,
3639 nullptr, &ctx.
paint);
3641 kDrawAtlasWithPaintFlags));
3660 return builder.Build();
3671 ctx.
canvas->DrawDisplayList(display_list);
3673 kDrawDisplayListFlags)
3674 .set_draw_display_list());
3681#if defined(OS_FUCHSIA)
3682 GTEST_SKIP() <<
"Rendering comparisons require a valid default font manager";
3686#ifdef IMPELLER_SUPPORTS_RENDERING
3705#ifdef IMPELLER_SUPPORTS_RENDERING
3714 .set_draw_text_blob(),
3835 kSaveLayerWithPaintFlags);
3836 CaseParameters case_params(
"Filtered SaveLayer with clipped content");
3844 test_params.imp_renderer());
3851 float commutable_color_matrix[]{
3859 float non_commutable_color_matrix[]{
3870 std::vector<SkScalar> opacities = {
3875 std::vector<std::shared_ptr<DlColorFilter>> color_filters = {
3878 std::make_shared<DlMatrixColorFilter>(commutable_color_matrix),
3879 std::make_shared<DlMatrixColorFilter>(non_commutable_color_matrix),
3883 std::vector<std::shared_ptr<DlImageFilter>> image_filters = {
3885 std::make_shared<DlDilateImageFilter>(5.0f, 5.0f),
3886 std::make_shared<DlErodeImageFilter>(5.0f, 5.0f),
3887 std::make_shared<DlMatrixImageFilter>(contract_matrix,
3906 auto test_attributes_env =
3908 const DlPaint& paint_both,
bool same,
bool rev_same,
3909 const std::string& desc1,
const std::string& desc2,
3914 render_content(nested_builder);
3915 auto nested_results =
env->getResult(nested_builder.
Build());
3920 render_content(reverse_builder);
3921 auto reverse_results =
env->getResult(reverse_builder.
Build());
3925 render_content(combined_builder);
3926 auto combined_results =
env->getResult(combined_builder.
Build());
3935 const bool always =
false;
3937 if (always || same) {
3939 nested_results.get(), combined_results.get(), same,
3940 "nested " + desc1 +
" then " + desc2);
3942 if (always || rev_same) {
3944 reverse_results.get(), combined_results.get(), rev_same,
3945 "nested " + desc2 +
" then " + desc1);
3949 auto test_attributes = [test_attributes_env](
DlPaint& paint1,
DlPaint& paint2,
3951 bool same,
bool rev_same,
3952 const std::string& desc1,
3953 const std::string& desc2) {
3956 auto env = std::make_unique<RenderEnvironment>(
3957 provider.get(), PixelFormat::kN32PremulPixelFormat);
3958 test_attributes_env(paint1, paint2, paint_both,
3959 same, rev_same, desc1, desc2,
env.get());
3965 for (
size_t cfi = 0; cfi < color_filters.size(); cfi++) {
3967 std::string cf_desc =
"color filter #" + std::to_string(cfi + 1);
3970 for (
size_t oi = 0; oi < opacities.size(); oi++) {
3972 std::string op_desc =
"opacity " + std::to_string(opacity);
3975 DlPaint combined_paint = nested_paint1;
3978 bool op_then_cf_works = opacity <= 0.0 || opacity >= 1.0 ||
3981 test_attributes(nested_paint1, nested_paint2, combined_paint,
true,
3982 op_then_cf_works, cf_desc, op_desc);
3990 for (
size_t oi = 0; oi < opacities.size(); oi++) {
3992 std::string op_desc =
"opacity " + std::to_string(opacity);
3995 for (
size_t ifi = 0; ifi < image_filters.size(); ifi++) {
3996 auto image_filter = image_filters[ifi];
3997 std::string if_desc =
"image filter #" + std::to_string(ifi + 1);
4000 DlPaint combined_paint = nested_paint1;
4003 bool if_then_op_works = opacity <= 0.0 || opacity >= 1.0;
4004 test_attributes(nested_paint1, nested_paint2, combined_paint,
true,
4005 if_then_op_works, op_desc, if_desc);
4011 for (
size_t cfi = 0; cfi < color_filters.size(); cfi++) {
4013 std::string cf_desc =
"color filter #" + std::to_string(cfi + 1);
4016 for (
size_t ifi = 0; ifi < image_filters.size(); ifi++) {
4017 auto image_filter = image_filters[ifi];
4018 std::string if_desc =
"image filter #" + std::to_string(ifi + 1);
4021 DlPaint combined_paint = nested_paint1;
4024 test_attributes(nested_paint1, nested_paint2, combined_paint,
true,
false,
4041 "matrix[" + std::to_string(element) +
"] = " + std::to_string(
value);
4042 float original_value = matrix[element];
4043 matrix[element] =
value;
4056 auto display_list1 = builder1.
Build();
4065 auto display_list2 = builder2.
Build();
4069 auto env = std::make_unique<RenderEnvironment>(
4070 provider.get(), PixelFormat::kN32PremulPixelFormat);
4071 auto results1 =
env->getResult(display_list1);
4072 auto results2 =
env->getResult(display_list2);
4075 desc +
" filter affects rendering");
4076 int modified_transparent_pixels =
4080 modified_transparent_pixels != 0)
4088 for (
int i = 0; i < 20; i++) {
4111 "matrix[" + std::to_string(element) +
"] = " + std::to_string(
value);
4112 matrix[element] =
value;
4114 EXPECT_EQ(std::isfinite(
value), filter !=
nullptr);
4127 auto display_list1 = builder1.
Build();
4136 auto display_list2 = builder2.
Build();
4140 auto env = std::make_unique<RenderEnvironment>(
4141 provider.get(), PixelFormat::kN32PremulPixelFormat);
4142 auto results1 =
env->getResult(display_list1);
4143 auto results2 =
env->getResult(display_list2);
4144 if (!filter || filter->can_commute_with_opacity()) {
4146 results2.get(), results1.get(), desc,
nullptr,
nullptr,
4150 results1.get(), results2.get(),
false, desc);
4158 for (
int i = 0; i < 20; i++) {
4170#define FOR_EACH_BLEND_MODE_ENUM(FUNC) \
4205#define MODE_CASE(m) \
4206 case DlBlendMode::m: \
4215 std::stringstream desc_str;
4217 desc_str <<
"blend[" << mode_string <<
", " <<
color <<
"]";
4218 std::string desc = desc_str.str();
4232 auto display_list1 = builder1.
Build();
4241 auto display_list2 = builder2.
Build();
4245 auto env = std::make_unique<RenderEnvironment>(
4246 provider.get(), PixelFormat::kN32PremulPixelFormat);
4247 auto results1 =
env->getResult(display_list1);
4248 auto results2 =
env->getResult(display_list2);
4249 int modified_transparent_pixels =
4253 modified_transparent_pixels != 0)
4266#define TEST_MODE(V) test_mode(DlBlendMode::V);
4273 std::stringstream desc_str;
4275 desc_str <<
"blend[" << mode_string <<
", " <<
color <<
"]";
4276 std::string desc = desc_str.str();
4296 auto display_list1 = builder1.
Build();
4305 auto display_list2 = builder2.
Build();
4309 auto env = std::make_unique<RenderEnvironment>(
4310 provider.get(), PixelFormat::kN32PremulPixelFormat);
4311 auto results1 =
env->getResult(display_list1);
4312 auto results2 =
env->getResult(display_list2);
4315 results2.get(), results1.get(), desc,
nullptr,
nullptr,
4319 results1.get(), results2.get(),
false, desc);
4332#define TEST_MODE(V) test_mode(DlBlendMode::V);
4358 const int step = 0x55;
4359 static_assert(
step * 3 == 255);
4361 for (
int r =
step; r < 256; r +=
step) {
4362 for (
int g =
step; g < 256; g +=
step) {
4370 static constexpr float color_filter_matrix_nomtb[] = {
4371 0.0001, 0.0001, 0.0001, 0.9997, 0.0,
4372 0.0001, 0.0001, 0.0001, 0.9997, 0.0,
4373 0.0001, 0.0001, 0.0001, 0.9997, 0.0,
4374 0.0001, 0.0001, 0.0001, 0.9997, 0.0,
4376 static constexpr float color_filter_matrix_mtb[] = {
4377 0.0001, 0.0001, 0.0001, 0.9997, 0.0,
4378 0.0001, 0.0001, 0.0001, 0.9997, 0.0,
4379 0.0001, 0.0001, 0.0001, 0.9997, 0.0,
4380 0.0001, 0.0001, 0.0001, 0.9997, 0.1,
4390 for (DlColor color : test_dst_colors) {
4392 paint.setColor(ToSk(color));
4393 paint.setBlendMode(SkBlendMode::kSrc);
4394 canvas->drawRect(SkRect::MakeXYWH(x, 0, 1, 1), paint);
4403 int data_count =
test_data->image()->width();
4405 data_count, data_count,
true, [
this, data_count](
SkCanvas* canvas) {
4406 ASSERT_EQ(
test_data->width(), data_count);
4408 for (
int y = 0;
y < data_count;
y++) {
4413 data_count, data_count,
true, [
this, data_count](
SkCanvas* canvas) {
4414 ASSERT_EQ(
test_data->width(), data_count);
4418 for (
int y = 0;
y < data_count;
y++) {
4423 for (
int y = 0;
y < data_count;
y++) {
4424 for (
int x = 0;
x < data_count;
x++) {
4433 static constexpr int kWasNotNop = 0x1;
4434 static constexpr int kWasMTB = 0x2;
4455 const std::function<
void(
SkCanvas*)>& renderer) {
4459 return std::make_unique<SkRenderResult>(
surface, snapshot);
4465 const std::string& desc) {
4467 bool is_error =
false;
4470 is_error = !dl->modifies_transparent_black();
4472 if (result_color != dst_color) {
4474 is_error = (dl->op_count() == 0u);
4477 FML_LOG(
ERROR) << std::hex << dst_color <<
" filters to " << result_color
4484 const std::unique_ptr<RenderResult>& result_data,
4486 const std::string& desc) {
4487 EXPECT_EQ(dst_data->width(), result_data->width());
4488 EXPECT_EQ(dst_data->height(), result_data->height());
4490 for (
int y = 0;
y < dst_data->height();
y++) {
4491 const uint32_t* dst_pixels = dst_data->addr32(0,
y);
4492 const uint32_t* result_pixels = result_data->addr32(0,
y);
4493 for (
int x = 0;
x < dst_data->width();
x++) {
4494 all_flags |= check_color_result(
DlColor(dst_pixels[
x]),
4495 DlColor(result_pixels[
x]), dl, desc);
4503 const std::string& desc) {
4504 if (!dl->modifies_transparent_black()) {
4506 }
else if ((all_flags & kWasMTB) == 0) {
4507 FML_LOG(INFO) <<
"combination does not affect transparency: " << desc;
4509 if (dl->op_count() == 0u) {
4511 }
else if ((all_flags & kWasNotNop) == 0) {
4512 FML_LOG(INFO) <<
"combination could be classified as a nop: " << desc;
4517 std::stringstream desc_stream;
4518 desc_stream <<
" using SkColorFilter::filterColor() with: ";
4520 desc_stream <<
"/" <<
color;
4521 std::string desc = desc_stream.str();
4524 builder.DrawRect({0.0f, 0.0f, 10.0f, 10.0f},
paint);
4525 auto dl = builder.Build();
4526 if (dl->modifies_transparent_black()) {
4527 ASSERT_TRUE(dl->op_count() != 0u);
4534 if (sk_color_filter) {
4535 for (
DlColor dst_color : test_dst_colors) {
4538 sk_color_filter->filterColor4f(dst_color_f, srgb.get(), srgb.get())
4540 all_flags |= check_color_result(dst_color,
result, dl, desc);
4542 if ((all_flags & kWasMTB) != 0) {
4543 EXPECT_FALSE(sk_color_filter->isAlphaUnchanged());
4546 report_results(all_flags, dl, desc);
4550 std::stringstream desc_stream;
4551 desc_stream <<
" rendering with: ";
4553 desc_stream <<
"/" <<
color;
4554 std::string desc = desc_stream.str();
4561 auto dl = builder.Build();
4562 bool dl_is_elided = dl->op_count() == 0u;
4563 bool dl_affects_transparent_pixels = dl->modifies_transparent_black();
4564 ASSERT_TRUE(!dl_is_elided || !dl_affects_transparent_pixels);
4572 auto result_surface = provider->MakeOffscreenSurface(
4575 SkCanvas* result_canvas = result_surface->sk_surface()->getCanvas();
4580 result_surface->sk_surface()->recordingContext())) {
4581 direct_context->flushAndSubmit();
4582 direct_context->flushAndSubmit(result_surface->sk_surface().get(),
4585 const std::unique_ptr<RenderResult> result_pixels =
4586 std::make_unique<SkRenderResult>(result_surface->sk_surface());
4588 int all_flags = check_image_result(test_data, result_pixels, dl, desc);
4589 report_results(all_flags, dl, desc);
4598 std::stringstream desc_stream;
4599 desc_stream <<
" rendering with: ";
4601 desc_stream <<
"/" <<
color;
4604 ?
"modifies transparency"
4605 :
"preserves transparency"
4607 desc_stream <<
", CF: " << cf_mtb;
4608 std::string if_mtb = image_filter
4610 ?
"modifies transparency"
4611 :
"preserves transparency"
4613 desc_stream <<
", IF: " << if_mtb;
4614 std::string desc = desc_stream.str();
4621 builder.DrawImage(
DlImage::Make(test_image_src_data->image()), {0, 0},
4623 auto dl = builder.Build();
4625 int w = test_image_src_data->width();
4626 int h = test_image_src_data->height();
4635 auto result_surface = provider->MakeOffscreenSurface(
4637 SkCanvas* result_canvas = result_surface->sk_surface()->getCanvas();
4639 result_canvas->
drawImage(test_image_dst_data->image(), 0, 0);
4640 result_canvas->
drawImage(test_image_src_data->image(), 0, 0,
4643 result_surface->sk_surface()->recordingContext())) {
4644 direct_context->flushAndSubmit();
4645 direct_context->flushAndSubmit(result_surface->sk_surface().get(),
4648 std::unique_ptr<RenderResult> result_pixels =
4649 std::make_unique<SkRenderResult>(result_surface->sk_surface());
4652 check_image_result(test_image_dst_data, result_pixels, dl, desc);
4653 report_results(all_flags, dl, desc);
4661 test_mode_color_via_filter(
mode,
color);
4665#define TEST_MODE(V) test_mode_filter(DlBlendMode::V);
4674 test_mode_color_via_rendering(
mode,
color);
4678#define TEST_MODE(V) test_mode_render(DlBlendMode::V);
4688 test_attributes_image(
mode,
color,
nullptr,
nullptr);
4689 test_attributes_image(
mode,
color, color_filter_nomtb.get(),
nullptr);
4690 test_attributes_image(
mode,
color, color_filter_mtb.get(),
nullptr);
4691 test_attributes_image(
mode,
color,
nullptr, &image_filter_nomtb);
4692 test_attributes_image(
mode,
color,
nullptr, &image_filter_mtb);
4696#define TEST_MODE(V) test_mode_render(DlBlendMode::V);
4701#undef FOR_EACH_BLEND_MODE_ENUM
static int step(int x, SkScalar min, SkScalar max)
static void test_bounds(skiatest::Reporter *reporter, SkClipStack::Element::DeviceSpaceType primType)
static bool match(const char *needle, const char *haystack)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
static void test_scale(skiatest::Reporter *reporter, const Geo &geo)
static const int points[]
static bool is_identity(const SkMatrix &m)
static void test_matrix(skiatest::Reporter *reporter)
@ kSrcOver
r = s + (1-sa)*d
@ kNormal_SkBlurStyle
fuzzy inside and outside
constexpr SkColor SK_ColorYELLOW
constexpr SkColor SK_ColorMAGENTA
constexpr SkColor SK_ColorCYAN
constexpr SkColor SK_ColorTRANSPARENT
constexpr SkColor SK_ColorBLUE
static constexpr SkColor SkColorSetA(SkColor c, U8CPU a)
constexpr SkColor SK_ColorRED
constexpr SkColor SK_ColorGREEN
@ kUTF8
uses bytes to represent UTF-8 or ASCII
static sk_sp< SkImage > color_filter(const SkImage *image, SkColorFilter *colorFilter)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
#define SK_ScalarInfinity
static void test_image(const sk_sp< SkSpecialImage > &img, skiatest::Reporter *reporter, GrRecordingContext *rContext, bool isGPUBacked)
void drawRect(const SkRect &rect, const SkPaint &paint)
void translate(SkScalar dx, SkScalar dy)
@ kFast_SrcRectConstraint
sample outside bounds; faster
void clear(SkColor color)
void rotate(SkScalar degrees)
SkMatrix getTotalMatrix() const
SkIRect getDeviceClipBounds() const
@ kLines_PointMode
draw each pair of points as a line segment
@ kPolygon_PointMode
draw the array of points as a open polygon
@ kPoints_PointMode
draw each point separately
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
static sk_sp< SkColorSpace > MakeSRGB()
static sk_sp< SkPathEffect > Make(const SkScalar intervals[], int count, SkScalar phase)
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkImageFilter > ColorFilter(sk_sp< SkColorFilter > cf, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Erode(SkScalar radiusX, SkScalar radiusY, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Blur(SkScalar sigmaX, SkScalar sigmaY, SkTileMode tileMode, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Dilate(SkScalar radiusX, SkScalar radiusY, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
static SkM44 Rotate(SkV3 axis, SkScalar radians)
SkM44 & preConcat(const SkM44 &m)
SkM44 & preTranslate(SkScalar x, SkScalar y, SkScalar z=0)
static sk_sp< SkMaskFilter > MakeBlur(SkBlurStyle style, SkScalar sigma, bool respectCTM=true)
static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2)
SkMatrix & setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
void setColor(SkColor color)
void setImageFilter(sk_sp< SkImageFilter > imageFilter)
@ kStroke_Style
set to stroke geometry
@ kFill_Style
set to fill geometry
void setShader(sk_sp< SkShader > shader)
@ kMiter_Join
extends to miter limit
@ kBevel_Join
connects outside edges
void setBlendMode(SkBlendMode mode)
SkShader * getShader() const
void setColorFilter(sk_sp< SkColorFilter > colorFilter)
SkPath & moveTo(SkScalar x, SkScalar y)
SkPath & lineTo(SkScalar x, SkScalar y)
SkPath & addRoundRect(const SkRect &rect, SkScalar rx, SkScalar ry, SkPathDirection dir=SkPathDirection::kCW)
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
sk_sp< SkPicture > finishRecordingAsPicture()
virtual void playback(SkCanvas *canvas, AbortCallback *callback=nullptr) const =0
const uint32_t * addr32() const
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
static sk_sp< SkTextBlob > MakeFromText(const void *text, size_t byteLength, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
static sk_sp< SkVertices > MakeCopy(VertexMode mode, int vertexCount, const SkPoint positions[], const SkPoint texs[], const SkColor colors[], int indexCount, const uint16_t indices[])
constexpr bool applies_color() const
constexpr bool is_stroked(DlDrawStyle style=DlDrawStyle::kStroke) const
constexpr bool applies_color_filter() const
constexpr bool ignores_paint() const
const DisplayListSpecialGeometryFlags WithPathEffect(const DlPathEffect *effect, bool is_stroked) const
constexpr bool applies_image_filter() const
constexpr bool applies_path_effect() const
constexpr bool applies_shader() const
constexpr bool applies_anti_alias() const
constexpr bool applies_mask_filter() const
constexpr bool applies_blend() const
The primitive honors the DlBlendMode.
constexpr bool is_flood() const
void DrawRect(const SkRect &rect, const DlPaint &paint) override
void Translate(SkScalar tx, SkScalar ty) override
void Rotate(SkScalar degrees) override
void SaveLayer(const SkRect *bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr) override
sk_sp< DisplayList > Build()
constexpr bool may_have_joins() const
The geometry may have segments connect non-continuously.
constexpr bool may_have_end_caps() const
The geometry may have segments that end without closing the path.
constexpr bool may_have_acute_joins() const
constexpr bool butt_cap_becomes_square() const
Mainly for drawPoints(PointMode) where Butt caps are rendered as squares.
static std::shared_ptr< DlColorFilter > Make(DlColor color, DlBlendMode mode)
bool can_commute_with_opacity() const override
bool modifies_transparent_black() const override
static std::shared_ptr< DlImageFilter > Make(SkScalar sigma_x, SkScalar sigma_y, DlTileMode tile_mode)
Developer-facing API for rendering anything within the engine.
virtual void DrawRect(const SkRect &rect, const DlPaint &paint)=0
virtual SkRect GetDestinationClipBounds() const =0
virtual SkISize GetBaseLayerSize() const =0
virtual SkMatrix GetTransform() const =0
static std::shared_ptr< DlLinearGradientColorSource > MakeLinear(const SkPoint start_point, const SkPoint end_point, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const SkMatrix *matrix=nullptr)
static std::shared_ptr< DlPathEffect > Make(const SkScalar intervals[], int count, SkScalar phase)
virtual bool modifies_transparent_black() const =0
static sk_sp< DlImage > Make(const SkImage *image)
static const std::shared_ptr< DlLinearToSrgbGammaColorFilter > kInstance
static std::shared_ptr< DlColorFilter > Make(const float matrix[20])
bool modifies_transparent_black() const override
DlStrokeCap getStrokeCap() const
DlPaint & setColor(DlColor color)
DlBlendMode getBlendMode() const
DlPaint & setColorFilter(const std::shared_ptr< const DlColorFilter > &filter)
float getStrokeMiter() const
std::shared_ptr< const DlPathEffect > getPathEffect() const
std::shared_ptr< const DlColorSource > getColorSource() const
DlStrokeJoin getStrokeJoin() const
DlPaint & setAlpha(uint8_t alpha)
DlPaint & setBlendMode(DlBlendMode mode)
DlDrawStyle getDrawStyle() const
std::shared_ptr< const DlMaskFilter > getMaskFilter() const
std::shared_ptr< const DlColorFilter > getColorFilter() const
DlPaint & setImageFilter(const std::shared_ptr< const DlImageFilter > &filter)
float getStrokeWidth() const
DlPaint & setOpacity(SkScalar opacity)
std::shared_ptr< const DlImageFilter > getImageFilter() const
DlPaint & setDrawStyle(DlDrawStyle style)
DlPaint & setColorSource(std::shared_ptr< const DlColorSource > source)
bool isInvertColors() const
Backend implementation of |DlCanvas| for |SkCanvas|.
void DrawDisplayList(const sk_sp< DisplayList > display_list, SkScalar opacity=SK_Scalar1) override
static void DrawShadow(SkCanvas *canvas, const SkPath &path, DlColor color, float elevation, bool transparentOccluder, SkScalar dpr)
static const std::shared_ptr< DlSrgbToLinearGammaColorFilter > kInstance
static std::shared_ptr< DlVertices > Make(DlVertexMode mode, int vertex_count, const SkPoint vertices[], const SkPoint texture_coordinates[], const DlColor colors[], int index_count=0, const uint16_t indices[]=nullptr)
Constructs a DlVector with compact inline storage for all of its required and optional lists of data.
static SkRect Scale(const SkRect &rect, const SkPoint &scales)
BoundsTolerance()=default
BoundsTolerance(const BoundsTolerance &)=default
BoundsTolerance addBoundsPadding(SkScalar bounds_pad_x, SkScalar bounds_pad_y) const
bool operator==(BoundsTolerance const &other) const
BoundsTolerance addPostClipPadding(SkScalar absolute_pad_x, SkScalar absolute_pad_y) const
SkScalar discrete_offset() const
bool overflows(SkIRect pix_bounds, int worst_bounds_pad_x, int worst_bounds_pad_y) const
BoundsTolerance addDiscreteOffset(SkScalar discrete_offset) const
BoundsTolerance clip(SkRect clip) const
BoundsTolerance mulScale(SkScalar scale_x, SkScalar scale_y) const
BoundsTolerance addAbsolutePadding(SkScalar absolute_pad_x, SkScalar absolute_pad_y) const
static std::vector< BackendType > TestBackends
static void showBoundsOverflow(const std::string &info, SkIRect &bounds, const BoundsTolerance *tolerance, int pixLeft, int pixTop, int pixRight, int pixBottom)
static void RenderWithAttributes(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance)
static int countModifiedTransparentPixels(const RenderResult *ref_result, const RenderResult *test_result)
static void RenderWithStrokes(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance_in)
static void SetupImpellerFailureImageDirectory()
static bool checkPixels(const RenderResult *ref_result, const SkRect ref_bounds, const std::string &info, const DlColor bg=DlColor::kTransparent())
static void RenderWithSaveRestore(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance)
static bool SaveImpellerFailureImages
static DirectoryStatus CheckDir(const std::string &dir)
static std::unique_ptr< DlSurfaceProvider > GetProvider(BackendType type)
static sk_sp< SkTextBlob > MakeTextBlob(const std::string &string, SkScalar font_height)
static void RenderWithClips(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &diff_tolerance)
static void RenderWith(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance_in, const CaseParameters &caseP)
static bool quickCompareToReference(const RenderResult *ref_result, const RenderResult *test_result, bool should_match, const std::string &info)
static void compareToReference(const RenderResult *test_result, const RenderResult *ref_result, const std::string &info, SkRect *bounds, const BoundsTolerance *tolerance, const DlColor bg, bool fuzzyCompares=false, int width=kTestWidth, int height=kTestHeight, bool printMismatches=false)
static void checkGroupOpacity(const RenderEnvironment &env, const sk_sp< DisplayList > &display_list, const RenderResult *ref_result, const std::string &info, DlColor bg)
static void save_to_png(const RenderResult *result, const std::string &op_desc, const std::string &reason)
static void RenderAll(const TestParameters ¶ms, const BoundsTolerance &tolerance=DefaultTolerance)
static bool AddProvider(BackendType type)
static std::vector< std::string > ImpellerFailureImages
static bool fuzzyCompare(uint32_t pixel_a, uint32_t pixel_b, int fudge)
static void quickCompareToReference(const RenderEnvironment &env, const std::string &info)
static void RenderWithTransforms(const TestParameters &testP, const RenderEnvironment &env, const BoundsTolerance &tolerance)
static BoundsTolerance DefaultTolerance
static std::string ImpellerFailureImageDirectory
static int groupOpacityFudgeFactor(const RenderEnvironment &env)
CaseParameters with_diff_clip()
bool fuzzy_compare_components() const
bool has_mutating_save_layer() const
bool has_diff_clip() const
CaseParameters(std::string info)
SkRenderer sk_restore() const
CaseParameters with_restore(SkRenderer &sk_restore, DlRenderer &dl_restore, bool mutating_layer, bool fuzzy_compare_components=false)
CaseParameters(std::string info, SkSetup &sk_setup, DlSetup &dl_setup, SkRenderer &sk_restore, DlRenderer &dl_restore, DlColor bg, bool has_diff_clip, bool has_mutating_save_layer, bool fuzzy_compare_components)
CaseParameters with_bg(DlColor bg)
CaseParameters(std::string info, SkSetup &sk_setup, DlSetup &dl_setup)
DlRenderer dl_restore() const
std::shared_ptr< DlColorFilter > color_filter_mtb
void test_attributes_image(DlBlendMode mode, DlColor color, DlColorFilter *color_filter, DlImageFilter *image_filter)
void report_results(int all_flags, const sk_sp< DisplayList > &dl, const std::string &desc)
std::unique_ptr< RenderResult > test_data
std::shared_ptr< DlColorFilter > color_filter_nomtb
int check_image_result(const std::unique_ptr< RenderResult > &dst_data, const std::unique_ptr< RenderResult > &result_data, const sk_sp< DisplayList > &dl, const std::string &desc)
std::unique_ptr< RenderResult > test_image_dst_data
std::vector< DlColor > test_dst_colors
void test_mode_color_via_rendering(DlBlendMode mode, DlColor color)
std::unique_ptr< RenderResult > test_image_src_data
int check_color_result(DlColor dst_color, DlColor result_color, const sk_sp< DisplayList > &dl, const std::string &desc)
std::vector< DlColor > test_src_colors
void test_mode_color_via_filter(DlBlendMode mode, DlColor color)
std::unique_ptr< RenderResult > get_output(int w, int h, bool snapshot, const std::function< void(SkCanvas *)> &renderer)
DisplayListRenderingTestBase()=default
static void SetUpTestSuite()
static bool StartsWith(std::string str, std::string prefix)
static void TearDownTestSuite()
virtual bool supports(PixelFormat format) const =0
virtual sk_sp< DlImage > MakeImpellerImage(const sk_sp< DisplayList > &list, int width, int height) const
virtual bool supports_impeller() const
static std::string BackendName(BackendType type)
static std::unique_ptr< DlSurfaceProvider > Create(BackendType backend_type)
virtual sk_sp< DlPixelData > ImpellerSnapshot(const sk_sp< DisplayList > &list, int width, int height) const
virtual std::shared_ptr< DlSurfaceInstance > MakeOffscreenSurface(size_t width, size_t height, PixelFormat format=kN32PremulPixelFormat) const =0
virtual const std::string backend_name() const =0
const SkRect & render_bounds() const
ImpellerRenderResult(sk_sp< DlPixelData > screenshot, SkRect render_bounds)
void write(const std::string &path) const override
int width() const override
~ImpellerRenderResult() override=default
int height() const override
const uint32_t * addr32(int x, int y) const override
sk_sp< SkImage > image() const override
void warn(const std::string &name)
OncePerBackendWarning(const std::string &warning)
std::unique_ptr< RenderResult > getResult(const RenderJobInfo &info, JobRenderer &renderer) const
const SkMatrix & ref_matrix() const
void init_ref(SkSetup &sk_setup, SkRenderer &sk_renderer, DlSetup &dl_setup, DlRenderer &dl_renderer, DlRenderer &imp_renderer, DlColor bg=DlColor::kTransparent())
std::unique_ptr< ImpellerRenderResult > getImpellerResult(const RenderJobInfo &info, DlJobRenderer &renderer) const
const DlPaint & ref_dl_paint() const
PixelFormat format() const
static RenderEnvironment MakeN32(const DlSurfaceProvider *provider)
const DlSurfaceProvider * provider() const
const sk_sp< SkImage > sk_image() const
const SkIRect & ref_clip_bounds() const
const sk_sp< DlImage > dl_image() const
RenderEnvironment(const DlSurfaceProvider *provider, PixelFormat format)
static RenderEnvironment Make565(const DlSurfaceProvider *provider)
bool supports_impeller() const
std::unique_ptr< RenderResult > getResult(sk_sp< DisplayList > dl) const
const std::string backend_name() const
const sk_sp< DlImage > impeller_image() const
const RenderResult * ref_dl_result() const
const ImpellerRenderResult * ref_impeller_result() const
const RenderResult * ref_sk_result() const
virtual int width() const =0
virtual const uint32_t * addr32(int x, int y) const =0
virtual int height() const =0
virtual ~RenderResult()=default
virtual sk_sp< SkImage > image() const =0
virtual void write(const std::string &path) const =0
static constexpr SkSamplingOptions kCubic
static constexpr SkSamplingOptions kMipmapLinear
static constexpr SkSamplingOptions kLinear
static constexpr SkSamplingOptions kNearestNeighbor
const uint32_t * addr32(int x, int y) const override
~SkRenderResult() override
SkRenderResult(const sk_sp< SkSurface > &surface, bool take_snapshot=false)
sk_sp< SkImage > image() const override
int width() const override
int height() const override
void write(const std::string &path) const
const BoundsTolerance lineAdjust(const BoundsTolerance &tolerance, const DlPaint &paint, const SkMatrix &matrix) const
TestParameters & set_draw_display_list()
TestParameters(const SkRenderer &sk_renderer, const DlRenderer &dl_renderer, const DisplayListAttributeFlags &flags)
const DlRenderer & imp_renderer() const
TestParameters & set_draw_text_blob()
TestParameters & set_vertical_line()
bool ignores_dashes() const
bool is_draw_display_list() const
bool is_draw_arc_center() const
TestParameters(const SkRenderer &sk_renderer, const DlRenderer &dl_renderer, const DlRenderer &imp_renderer, const DisplayListAttributeFlags &flags)
TestParameters & set_draw_path()
bool uses_gradient() const
const BoundsTolerance adjust(const BoundsTolerance &tolerance, const DlPaint &paint, const SkMatrix &matrix) const
TestParameters & set_ignores_dashes()
bool is_draw_path() const
bool is_horizontal_line() const
TestParameters & set_draw_line()
bool is_draw_line() const
TestParameters & set_draw_arc_center()
TestParameters & set_horizontal_line()
bool is_draw_text_blob() const
bool is_vertical_line() const
const DlRenderer & dl_renderer() const
bool impeller_compatible(const DlPaint &paint) const
bool should_match(const RenderEnvironment &env, const CaseParameters &caseP, const DlPaint &attr, const MatrixClipJobRenderer &renderer) const
DlStrokeCap getCap(const DlPaint &attr, DisplayListSpecialGeometryFlags geo_flags) const
const SkRenderer & sk_renderer() const
#define FOR_EACH_BLEND_MODE_ENUM(FUNC)
const EmbeddedViewParams * params
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define FML_LOG(severity)
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
static void draw_rect(SkCanvas *canvas, SkImage *, const SkRect &r, sk_sp< SkImageFilter > imf)
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
constexpr SkScalar kXOffsetR3
const std::function< void(const SkRenderContext &)> SkRenderer
constexpr int kTestHeight
constexpr SkScalar kYOffsetD3
TEST_F(DisplayListTest, Defaults)
const std::function< void(const DlSetupContext &)> DlSetup
static void DrawCheckerboard(DlCanvas *canvas)
constexpr SkPoint kVerticalMiterDiamondPoints[]
constexpr int kRenderCenterY
constexpr int kRenderCenterX
constexpr int kRenderRight
static std::string BlendModeToString(DlBlendMode mode)
constexpr SkScalar kXOffsetR1
static const DlSetup kEmptyDlSetup
constexpr SkScalar kYOffsetD1
SkFont CreateTestFontOfSize(SkScalar scalar)
static const SkRenderer kEmptySkRenderer
constexpr SkScalar kMiterExtremeDiamondOffsetX
sk_sp< DisplayList > makeTestDisplayList()
constexpr SkScalar kYOffsetU2
const int kHorizontalMiterDiamondPointCount
constexpr SkScalar kXOffsetL3
constexpr SkScalar kMiter4DiamondOffsetY
static std::shared_ptr< DlImageColorSource > MakeColorSource(const sk_sp< DlImage > &image)
constexpr int kRenderBottom
constexpr int kRenderHalfHeight
constexpr SkScalar kYOffsetD2
constexpr int kRenderHalfWidth
constexpr SkRect kTestBounds2
constexpr SkScalar kXOffsetR2
constexpr int kRenderHeight
const std::function< void(const SkSetupContext &)> SkSetup
DlCanvas::PointMode PointMode
constexpr SkScalar kXOffsetL1
constexpr SkScalar kMiter10DiamondOffsetY
constexpr int kRenderWidth
constexpr SkScalar kMiter10DiamondOffsetX
const SkPoint kHorizontalMiterDiamondPoints[]
constexpr SkScalar kYOffset0
constexpr SkRect kRenderBounds
constexpr SkScalar kYOffsetU1
constexpr SkScalar kYOffsetU3
const int kVerticalMiterDiamondPointCount
constexpr int kRenderLeft
static const DlRenderer kEmptyDlRenderer
static const SkSetup kEmptySkSetup
constexpr SkScalar kXOffset0
constexpr SkScalar kMiter4DiamondOffsetX
constexpr SkScalar kRenderCornerRadius
constexpr SkScalar kXOffsetL2
constexpr SkScalar kRenderRadius
const std::function< void(const DlRenderContext &)> DlRenderer
constexpr SkPoint kTestCenter
constexpr SkScalar kMiterExtremeDiamondOffsetY
SkPaint ToSk(const DlPaint &paint)
@ kMiter
extends to miter limit
@ kBevel
connects outside edges
bool NotEquals(const T *a, const T *b)
@ kButt
no stroke extension
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
DEF_SWITCHES_START aot vmservice shared library name
@ kTriangles
The vertices are taken 3 at a time to form a triangle.
@ kStroke
strokes boundary of shapes
@ kFill
fills interior of shapes
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
@ kNormal
fuzzy inside and outside
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
TEST_F(EngineAnimatorTest, AnimatorAcceptsMultipleRenders)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder h
@ kSrcOver
r = s + (1-sa)*d
@ kSrcATop
r = s*da + d*(1-sa)
fml::UniqueFD OpenDirectory(const char *path, bool create_if_necessary, FilePermission permission)
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
int32_t fBottom
larger y-axis bounds
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
constexpr SkISize size() const
int32_t fTop
smaller y-axis bounds
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
SkIRect makeInset(int32_t dx, int32_t dy) const
int32_t fLeft
smaller x-axis bounds
bool contains(int32_t x, int32_t y) const
int32_t fRight
larger x-axis bounds
constexpr int32_t width() const
constexpr int32_t height() const
constexpr int64_t area() const
static SkImageInfo MakeN32Premul(int width, int height)
static constexpr SkPoint Make(float x, float y)
static SkRGBA4f FromColor(SkColor color)
static SkRect Make(const SkISize &size)
SkScalar fBottom
larger y-axis bounds
constexpr SkRect makeOffset(float dx, float dy) const
bool intersect(const SkRect &r)
SkScalar fLeft
smaller x-axis bounds
static SkRect MakeIWH(int w, int h)
void outset(float dx, float dy)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
SkRect makeInset(float dx, float dy) const
SkScalar fRight
larger x-axis bounds
bool contains(SkScalar x, SkScalar y) const
void roundOut(SkIRect *dst) const
static constexpr SkRect MakeWH(float w, float h)
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
SkScalar fTop
smaller y-axis bounds
static constexpr DlColor kMagenta()
static constexpr DlColor kWhite()
static constexpr DlColor kBlue()
static constexpr DlColor kBlack()
static constexpr DlColor kYellow()
static constexpr DlColor kLightGrey()
constexpr DlColor withAlpha(uint8_t alpha) const
constexpr uint32_t premultipliedArgb() const
static constexpr DlColor kTransparent()
static constexpr DlColor kRed()
static constexpr DlColor kGreen()
constexpr bool isTransparent() const
static constexpr DlColor kDarkGrey()
static constexpr DlColor kCyan()
constexpr uint32_t argb() const
void Render(SkCanvas *canvas, const RenderJobInfo &info)
DisplayListJobRenderer(sk_sp< DisplayList > display_list)
void Render(DlCanvas *canvas, const RenderJobInfo &info)
sk_sp< DisplayList > MakeDisplayList(const RenderJobInfo &info)
bool targets_impeller() const override
const DlPaint & setup_paint() const
void Render(SkCanvas *sk_canvas, const RenderJobInfo &info) override
DlJobRenderer(const DlSetup &dl_setup, const DlRenderer &dl_render, const DlRenderer &dl_restore, const sk_sp< DlImage > &dl_image)
virtual void Render(SkCanvas *canvas, const RenderJobInfo &info)=0
virtual bool targets_impeller() const
SkIRect setup_clip_bounds_
const SkIRect & setup_clip_bounds() const
const SkMatrix & setup_matrix() const
SkJobRenderer(const SkSetup &sk_setup, const SkRenderer &sk_render, const SkRenderer &sk_restore, const sk_sp< SkImage > &sk_image)
void Render(SkCanvas *canvas, const RenderJobInfo &info) override
const SkPaint & setup_paint() const
sk_sp< SkPicture > MakePicture(const RenderJobInfo &info)
void Render(SkCanvas *canvas, const RenderJobInfo &info)
SkPictureJobRenderer(sk_sp< SkPicture > picture)
#define EXPECT_TRUE(handle)