Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit e065398

Browse files
authored
use TextFrame calls for Impeller in rendertests (#46696)
Switch the impeller testing in rendertests to use TextFrame objects rather than TextBlob objects when drawing to an Impeller-managed destination. Previously the DrawText tests would generate over 200 errors because none of the attribute variants would render anything at all. After this fix the number of failures in the DrawText calls is down to 1 which points out that wrapping a DrawTextFrame call in a nothing saveLayer somehow affects the glyph positioning (in a not very appealing manner).
1 parent 39bfce2 commit e065398

4 files changed

Lines changed: 92 additions & 29 deletions

File tree

display_list/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ if (enable_unittests) {
155155
"//flutter/common/graphics",
156156
"//flutter/display_list/testing:display_list_surface_provider",
157157
"//flutter/display_list/testing:display_list_testing",
158+
"//flutter/impeller/typographer/backends/skia:typographer_skia_backend",
158159
"//flutter/testing",
159160
]
160161

display_list/testing/dl_rendering_unittests.cc

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
#include "flutter/fml/math.h"
1717
#include "flutter/testing/display_list_testing.h"
1818
#include "flutter/testing/testing.h"
19+
#ifdef IMPELLER_SUPPORTS_RENDERING
20+
#include "flutter/impeller/typographer/backends/skia/text_frame_skia.h"
21+
#endif // IMPELLER_SUPPORTS_RENDERING
1922

2023
#include "third_party/skia/include/core/SkBBHFactory.h"
2124
#include "third_party/skia/include/core/SkColorFilter.h"
@@ -592,16 +595,11 @@ class RenderEnvironment {
592595
return RenderEnvironment(provider, PixelFormat::kN32PremulPixelFormat);
593596
}
594597

595-
void init_ref(SkRenderer& sk_renderer,
596-
DlRenderer& dl_renderer,
597-
DlColor bg = DlColor::kTransparent()) {
598-
init_ref(kEmptySkSetup, sk_renderer, kEmptyDlSetup, dl_renderer, bg);
599-
}
600-
601598
void init_ref(SkSetup& sk_setup,
602599
SkRenderer& sk_renderer,
603600
DlSetup& dl_setup,
604601
DlRenderer& dl_renderer,
602+
DlRenderer& imp_renderer,
605603
DlColor bg = DlColor::kTransparent()) {
606604
SkJobRenderer sk_job(sk_setup, sk_renderer, kEmptySkRenderer, kTestSkImage);
607605
RenderJobInfo info = {
@@ -617,7 +615,7 @@ class RenderEnvironment {
617615
ASSERT_EQ(sk_job.setup_clip_bounds(), ref_clip_bounds_);
618616
if (provider_->supports_impeller()) {
619617
test_impeller_image_ = makeTestImpellerImage(provider_);
620-
DlJobRenderer imp_job(dl_setup, dl_renderer, kEmptyDlRenderer,
618+
DlJobRenderer imp_job(dl_setup, imp_renderer, kEmptyDlRenderer,
621619
test_impeller_image_);
622620
ref_impeller_result_ = getImpellerResult(info, imp_job);
623621
}
@@ -818,11 +816,34 @@ class TestParameters {
818816
TestParameters(const SkRenderer& sk_renderer,
819817
const DlRenderer& dl_renderer,
820818
const DisplayListAttributeFlags& flags)
821-
: sk_renderer_(sk_renderer), dl_renderer_(dl_renderer), flags_(flags) {}
819+
: TestParameters(sk_renderer, dl_renderer, dl_renderer, flags) {}
820+
821+
TestParameters(const SkRenderer& sk_renderer,
822+
const DlRenderer& dl_renderer,
823+
const DlRenderer& imp_renderer,
824+
const DisplayListAttributeFlags& flags)
825+
: sk_renderer_(sk_renderer),
826+
dl_renderer_(dl_renderer),
827+
imp_renderer_(imp_renderer),
828+
flags_(flags) {}
822829

823830
bool uses_paint() const { return !flags_.ignores_paint(); }
824831
bool uses_gradient() const { return flags_.applies_shader(); }
825832

833+
bool impeller_compatible(const DlPaint& paint) const {
834+
if (is_draw_text_blob()) {
835+
// Non-color text is rendered as paths
836+
if (paint.getColorSourcePtr() && !paint.getColorSourcePtr()->asColor()) {
837+
return false;
838+
}
839+
// Non-filled text (stroke or stroke and fill) is rendered as paths
840+
if (paint.getDrawStyle() != DlDrawStyle::kFill) {
841+
return false;
842+
}
843+
}
844+
return true;
845+
}
846+
826847
bool should_match(const RenderEnvironment& env,
827848
const CaseParameters& caseP,
828849
const DlPaint& attr,
@@ -1015,6 +1036,7 @@ class TestParameters {
10151036

10161037
const SkRenderer& sk_renderer() const { return sk_renderer_; }
10171038
const DlRenderer& dl_renderer() const { return dl_renderer_; }
1039+
const DlRenderer& imp_renderer() const { return imp_renderer_; }
10181040

10191041
// Tests that call drawTextBlob with an sk_ref paint attribute will cause
10201042
// those attributes to be stored in an internal Skia cache so we need
@@ -1065,6 +1087,7 @@ class TestParameters {
10651087
private:
10661088
const SkRenderer sk_renderer_;
10671089
const DlRenderer dl_renderer_;
1090+
const DlRenderer imp_renderer_;
10681091
const DisplayListAttributeFlags flags_;
10691092

10701093
bool is_draw_text_blob_ = false;
@@ -1110,7 +1133,8 @@ class CanvasCompareTester {
11101133
for (auto& back_end : kTestBackends) {
11111134
auto provider = GetProvider(back_end);
11121135
RenderEnvironment env = RenderEnvironment::MakeN32(provider.get());
1113-
env.init_ref(params.sk_renderer(), params.dl_renderer());
1136+
env.init_ref(kEmptySkSetup, params.sk_renderer(), //
1137+
kEmptyDlSetup, params.dl_renderer(), params.imp_renderer());
11141138
quickCompareToReference(env, "default");
11151139
if (env.supports_impeller()) {
11161140
auto impeller_result = env.ref_impeller_result();
@@ -1279,7 +1303,8 @@ class CanvasCompareTester {
12791303
ctx.paint.setAlpha(ctx.paint.getAlpha() / 2);
12801304
};
12811305
backdrop_env.init_ref(sk_backdrop_setup, testP.sk_renderer(),
1282-
dl_backdrop_setup, testP.dl_renderer());
1306+
dl_backdrop_setup, testP.dl_renderer(),
1307+
testP.imp_renderer());
12831308
quickCompareToReference(backdrop_env, "backdrop");
12841309

12851310
DlBlurImageFilter dl_backdrop(5, 5, DlTileMode::kDecal);
@@ -1463,7 +1488,7 @@ class CanvasCompareTester {
14631488
[=](const SkSetupContext& ctx) { sk_aa_setup(ctx, false); },
14641489
testP.sk_renderer(),
14651490
[=](const DlSetupContext& ctx) { dl_aa_setup(ctx, false); },
1466-
testP.dl_renderer());
1491+
testP.dl_renderer(), testP.imp_renderer());
14671492
quickCompareToReference(aa_env, "AntiAlias");
14681493
RenderWith(
14691494
testP, aa_env, aa_tolerance,
@@ -1547,7 +1572,8 @@ class CanvasCompareTester {
15471572
ctx.paint.setStrokeWidth(5.0);
15481573
};
15491574
blur_env.init_ref(sk_blur_setup, testP.sk_renderer(), //
1550-
dl_blur_setup, testP.dl_renderer());
1575+
dl_blur_setup, testP.dl_renderer(),
1576+
testP.imp_renderer());
15511577
quickCompareToReference(blur_env, "blur");
15521578
DlBlurImageFilter dl_filter_decal_5(5.0, 5.0, DlTileMode::kDecal);
15531579
auto sk_filter_decal_5 =
@@ -1598,7 +1624,8 @@ class CanvasCompareTester {
15981624
ctx.paint.setStrokeWidth(5.0);
15991625
};
16001626
dilate_env.init_ref(sk_dilate_setup, testP.sk_renderer(), //
1601-
dl_dilate_setup, testP.dl_renderer());
1627+
dl_dilate_setup, testP.dl_renderer(),
1628+
testP.imp_renderer());
16021629
quickCompareToReference(dilate_env, "dilate");
16031630
DlDilateImageFilter dl_dilate_filter_5(5.0, 5.0);
16041631
auto sk_dilate_filter_5 = SkImageFilters::Dilate(5.0, 5.0, nullptr);
@@ -1629,7 +1656,8 @@ class CanvasCompareTester {
16291656
ctx.paint.setStrokeWidth(6.0);
16301657
};
16311658
erode_env.init_ref(sk_erode_setup, testP.sk_renderer(), //
1632-
dl_erode_setup, testP.dl_renderer());
1659+
dl_erode_setup, testP.dl_renderer(),
1660+
testP.imp_renderer());
16331661
quickCompareToReference(erode_env, "erode");
16341662
// do not erode too much, because some tests assert there are enough
16351663
// pixels that are changed.
@@ -1779,7 +1807,8 @@ class CanvasCompareTester {
17791807
ctx.paint.setStrokeWidth(5.0);
17801808
};
17811809
dither_env.init_ref(sk_dither_setup, testP.sk_renderer(),
1782-
dl_dither_setup, testP.dl_renderer(), dither_bg);
1810+
dl_dither_setup, testP.dl_renderer(),
1811+
testP.imp_renderer(), dither_bg);
17831812
quickCompareToReference(dither_env, "dither");
17841813
RenderWith(testP, dither_env, tolerance,
17851814
CaseParameters(
@@ -1875,7 +1904,8 @@ class CanvasCompareTester {
18751904
ctx.paint.setStrokeWidth(5.0);
18761905
};
18771906
stroke_base_env.init_ref(sk_stroke_setup, testP.sk_renderer(),
1878-
dl_stroke_setup, testP.dl_renderer());
1907+
dl_stroke_setup, testP.dl_renderer(),
1908+
testP.imp_renderer());
18791909
quickCompareToReference(stroke_base_env, "stroke");
18801910

18811911
RenderWith(testP, stroke_base_env, tolerance,
@@ -2296,10 +2326,16 @@ class CanvasCompareTester {
22962326
info + " (attribute should affect rendering)");
22972327
}
22982328

2299-
if (env.supports_impeller()) {
2300-
DlJobRenderer imp_job(caseP.dl_setup(), //
2301-
testP.dl_renderer(), //
2302-
caseP.dl_restore(), //
2329+
// If either the reference setup or the test setup contain attributes
2330+
// that Impeller doesn't support, we skip the Impeller testing. This
2331+
// is mostly stroked or patterned text which is vectored through drawPath
2332+
// for Impeller.
2333+
if (env.supports_impeller() &&
2334+
testP.impeller_compatible(dl_job.setup_paint()) &&
2335+
testP.impeller_compatible(env.ref_dl_paint())) {
2336+
DlJobRenderer imp_job(caseP.dl_setup(), //
2337+
testP.imp_renderer(), //
2338+
caseP.dl_restore(), //
23032339
env.impeller_image());
23042340
auto imp_result = env.getImpellerResult(base_info, imp_job);
23052341
std::string imp_info = info + " (Impeller)";
@@ -2317,7 +2353,8 @@ class CanvasCompareTester {
23172353
imp_info + " (attribute should affect rendering)");
23182354
}
23192355
if (!success) {
2320-
FML_LOG(ERROR) << "Impeller issue encountered for: " << *display_list;
2356+
FML_LOG(ERROR) << "Impeller issue encountered for: "
2357+
<< *imp_job.MakeDisplayList(base_info);
23212358
std::string filename = to_png_filename(info + " (Impeller Output)");
23222359
imp_result->write(filename);
23232360
FML_LOG(ERROR) << "output saved in: " << filename;
@@ -3621,6 +3658,9 @@ TEST_F(DisplayListRendering, DrawTextBlob) {
36213658
#else
36223659
sk_sp<SkTextBlob> blob =
36233660
CanvasCompareTester::MakeTextBlob("Testing", kRenderHeight * 0.33f);
3661+
#ifdef IMPELLER_SUPPORTS_RENDERING
3662+
auto frame = impeller::MakeTextFrameFromTextBlobSkia(blob);
3663+
#endif // IMPELLER_SUPPORTS_RENDERING
36243664
SkScalar render_y_1_3 = kRenderTop + kRenderHeight * 0.3;
36253665
SkScalar render_y_2_3 = kRenderTop + kRenderHeight * 0.6;
36263666
CanvasCompareTester::RenderAll( //
@@ -3637,6 +3677,14 @@ TEST_F(DisplayListRendering, DrawTextBlob) {
36373677
ctx.canvas->DrawTextBlob(blob, kRenderLeft, render_y_2_3, paint);
36383678
ctx.canvas->DrawTextBlob(blob, kRenderLeft, kRenderBottom, paint);
36393679
},
3680+
#ifdef IMPELLER_SUPPORTS_RENDERING
3681+
[=](const DlRenderContext& ctx) {
3682+
auto paint = ctx.paint;
3683+
ctx.canvas->DrawTextFrame(frame, kRenderLeft, render_y_1_3, paint);
3684+
ctx.canvas->DrawTextFrame(frame, kRenderLeft, render_y_2_3, paint);
3685+
ctx.canvas->DrawTextFrame(frame, kRenderLeft, kRenderBottom, paint);
3686+
},
3687+
#endif // IMPELLER_SUPPORTS_RENDERING
36403688
kDrawTextBlobFlags)
36413689
.set_draw_text_blob(),
36423690
// From examining the bounds differential for the "Default" case, the
@@ -3766,7 +3814,9 @@ TEST_F(DisplayListRendering, SaveLayerClippedContentStillFilters) {
37663814
for (auto& back_end : CanvasCompareTester::kTestBackends) {
37673815
auto provider = CanvasCompareTester::GetProvider(back_end);
37683816
RenderEnvironment env = RenderEnvironment::MakeN32(provider.get());
3769-
env.init_ref(test_params.sk_renderer(), test_params.dl_renderer());
3817+
env.init_ref(kEmptySkSetup, test_params.sk_renderer(), //
3818+
kEmptyDlSetup, test_params.dl_renderer(),
3819+
test_params.imp_renderer());
37703820
CanvasCompareTester::quickCompareToReference(env, "default");
37713821
CanvasCompareTester::RenderWith(test_params, env, tolerance, case_params);
37723822
}

testing/display_list_testing.cc

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,17 @@ static std::ostream& operator<<(std::ostream& os, const SkTextBlob* blob) {
287287
return os << "&SkTextBlob(ID: " << blob->uniqueID() << ", " << blob->bounds() << ")";
288288
}
289289

290+
static std::ostream& operator<<(std::ostream& os,
291+
const impeller::TextFrame* frame) {
292+
if (frame == nullptr) {
293+
return os << "no text";
294+
}
295+
auto bounds = frame->GetBounds();
296+
return os << "&TextFrame("
297+
<< bounds.GetLeft() << ", " << bounds.GetTop() << " => "
298+
<< bounds.GetRight() << ", " << bounds.GetBottom() << ")";
299+
}
300+
290301
std::ostream& operator<<(std::ostream& os, const DlVertexMode& mode) {
291302
switch (mode) {
292303
case DlVertexMode::kTriangles: return os << "VertexMode::kTriangles";
@@ -860,12 +871,13 @@ void DisplayListStreamDispatcher::drawTextBlob(const sk_sp<SkTextBlob> blob,
860871
<< x << ", " << y << ");" << std::endl;
861872
}
862873

863-
void DisplayListStreamDispatcher::drawTextFrame(const std::shared_ptr<impeller::TextFrame>& text_frame,
864-
SkScalar x,
865-
SkScalar y) {
866-
startl() << "drawTextFrame("
867-
<< text_frame.get() << ", "
868-
<< x << ", " << y << ");" << std::endl;
874+
void DisplayListStreamDispatcher::drawTextFrame(
875+
const std::shared_ptr<impeller::TextFrame>& text_frame,
876+
SkScalar x,
877+
SkScalar y) {
878+
startl() << "drawTextFrame("
879+
<< text_frame.get() << ", "
880+
<< x << ", " << y << ");" << std::endl;
869881
}
870882

871883
void DisplayListStreamDispatcher::drawShadow(const SkPath& path,

third_party/txt/src/skia/paragraph_skia.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ class DisplayListParagraphPainter : public skt::ParagraphPainter {
213213
// filters rely on having the glyph coverage, whereas regular text is
214214
// drawn as rectangular texture samples.
215215
return ((paint.getColorSource() && !paint.getColorSource()->asColor()) ||
216-
paint.getDrawStyle() == DlDrawStyle::kStroke);
216+
paint.getDrawStyle() != DlDrawStyle::kFill);
217217
}
218218

219219
DlPaint toDlPaint(const DecorationStyle& decor_style,

0 commit comments

Comments
 (0)