-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Refactor text and runtime effect to separate skia and impeller implementations. #174219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor text and runtime effect to separate skia and impeller implementations. #174219
Conversation
flar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some things I should have noted before, but most of them are style and better testing related...
.vscode/settings.json
Outdated
| ], | ||
| "files.trimTrailingWhitespace": true | ||
| "files.trimTrailingWhitespace": true, | ||
| "files.associations": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this part of the other PR? It doesn't make sense as part of this PR unless I've missed something...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gahhh this freaking file keeps changing itself and I accidentally added it. I will unstage this change.
| receiver.drawTextFrame(text_frame, x, y); | ||
| DisplayListCompare equals(const DrawTextOp* other) const { | ||
| return text->getTextBlob() == other->text->getTextBlob() && | ||
| text->getTextFrame() == other->text->getTextFrame() && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps put this pointer comparison inside a DlText::== operator to hide the details (and in case we eventually have some better way to compare them than by (pair of) subsumed pointer(s)?)
| namespace flutter { | ||
| class DlText { | ||
| public: | ||
| virtual DlRect getBounds() const = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know there is a mixed style in DL objects, but I think we are moving towards capitalized getters like GetBounds, GetTextFrame, etc. I wasn't doing that until I started integrating with Impeller, but I think it is better matched to the C++ style guidelines so I'd like to move in that direction.
Technically you can have a strict getter that is lower case, but I don't think either of getTextFoo() are "strict getters" since they are only defined for specific subclasses...
| #define FLUTTER_DISPLAY_LIST_DL_TEXT_H_ | ||
|
|
||
| #include "flutter/display_list/geometry/dl_geometry_types.h" | ||
| #include "third_party/skia/include/core/SkRefCnt.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can change the getter to SkTextBlob* and we won't need SkRefCnt included here...?
| public: | ||
| virtual DlRect getBounds() const = 0; | ||
| virtual std::shared_ptr<impeller::TextFrame> getTextFrame() const = 0; | ||
| virtual sk_sp<SkTextBlob> getTextBlob() const = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One of the magic things about sk_sp is that you can just use a raw pointer in cases where you are just passing it along (because the ref count is built-in and there is free "shared from this"). So, this could return SkTextBlob*. Indeed, if you look at SkCanvas::drawTextBlob, the real method takes the ptr and the version that takes an sk_sp does a get() on it and passes it to the pointer version...
| #include "flutter/flow/surface_frame.h" | ||
| #include "flutter/fml/macros.h" | ||
|
|
||
| #include "third_party/skia/include/core/SkData.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this for the DlText changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SurfaceData below uses an SkData. I think we previously got away with it through some kind of transitive include.
| } | ||
| // 2x3 2D affine subset of a 4x4 transform in row major order | ||
| void FirstPassDispatcher::transform2DAffine( | ||
| DlScalar mxx, DlScalar mxy, DlScalar mxt, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think your indent is off by 2 for these. Argument continuations are indented 4 spots, not 2. Same for FullPerspective below...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These still look off by 2. You got the ones inside the method body, but these argument methods should also be indented by 4 as well.
| RUN_TESTS2(canvas.DrawDisplayList(display_list);, false); | ||
| } | ||
| RUN_TESTS2(canvas.DrawTextBlob(GetTestTextBlob(1), 0, 0, paint);, false); | ||
| RUN_TESTS2(canvas.DrawText(DlTextSkia::Make(GetTestTextBlob(1)), 0, 0, paint); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no test for Impeller Text here (and the one test for it down below is testing a different condition). While the builder code is the same for both, it couldn't hurt to have both tested here so that when we eventually delete Skia we aren't left without any "text" case for this test.
| DlBlendMode::kSrcOver, DlImageSampling::kLinear, | ||
| nullptr, &paint); | ||
| builder.DrawTextBlob(GetTestTextBlob(1), 10, 10, paint); | ||
| builder.DrawText(DlTextSkia::Make(GetTestTextBlob(1)), 10, 10, paint); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also need a test to make sure that DrawText(Impeller) is also nop'd.
| ASSERT_LT(blob->bounds().width(), draw_rect.GetWidth()); | ||
| ASSERT_LT(blob->bounds().height(), draw_rect.GetHeight()); | ||
|
|
||
| auto text = DlTextImpeller::Make(frame); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or, makefromblob above instead of blob->frame->text.
| } | ||
| std::shared_ptr<DlText> text; | ||
| if (impeller_enabled_) { | ||
| #if IMPELLER_SUPPORTS_RENDERING |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this have the if inside it as well? Otherwise we might have a mismatch? Or is that possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's possible for that to happen, but I can switch this up to cover the whole if statement.
| return text->GetTextBlob() == other->text->GetTextBlob() && | ||
| text->GetTextFrame() == other->text->GetTextFrame() && | ||
| x == other->x && y == other->y | ||
| return text == other->text && x == other->x && y == other->y |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this only compares the shared pointers. You can use the Equals mechanism (see SetSharedImageFilterOp) which does pointer comparisons and then also *foo == *bar comparisons if needed. You could also do *text == *(other->text), but that gets dangerous if one of them is null. The Equals family of methods protects against that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Equals(text, other->text)
| // clang-format off | ||
| // full 4x4 transform in row major order | ||
| void FirstPassDispatcher::transformFullPerspective( | ||
| DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These argument methods are also indented off by 2.
|
|
||
| DisplayListCompare equals(const DrawTextOp* other) const { | ||
| return text == other->text && x == other->x && y == other->y | ||
| return *text == *other->text && x == other->x && y == other->y |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer Equals(text, other->text), but this is likely safe in practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I just reread your comment, I switched it to use Equals() instead
…ler implementations. (flutter/flutter#174219)
…ler implementations. (flutter/flutter#174219)
flutter/flutter@26bb33b...edd434a 2025-08-23 [email protected] Roll Skia from 6f710e0b38f7 to 61169c1f6f7c (1 revision) (flutter/flutter#174325) 2025-08-23 [email protected] Roll Fuchsia Linux SDK from Z-ZaFQ7jAqJ1OrIBf... to XLSNQCsY1VkIthSjt... (flutter/flutter#174318) 2025-08-23 [email protected] Roll Skia from ebb6051e8bb1 to 6f710e0b38f7 (1 revision) (flutter/flutter#174317) 2025-08-22 [email protected] [web] Expose rasterizers in Renderer (flutter/flutter#174308) 2025-08-22 [email protected] Update some semantics flags updated to use enum (engine, framework, web) (flutter/flutter#170696) 2025-08-22 [email protected] [ Tool ] Don't emit artifact downloading messages when --machine is provided (flutter/flutter#174301) 2025-08-22 [email protected] Roll Skia from cb15e1452399 to ebb6051e8bb1 (5 revisions) (flutter/flutter#174296) 2025-08-22 [email protected] `_downloadArtifacts` (Web SDK) uses content-aware hashing in post-submit (flutter/flutter#174236) 2025-08-22 [email protected] Refactor text and runtime effect to separate skia and impeller implementations. (flutter/flutter#174219) 2025-08-22 [email protected] Roll Packages from 58c02e0 to 092d832 (4 revisions) (flutter/flutter#174295) 2025-08-22 [email protected] [ Widget Preview ] Add support for DevTools configuration (flutter/flutter#174272) 2025-08-22 [email protected] Migrate more files to `WidgetStateProperty` (flutter/flutter#174268) 2025-08-22 [email protected] [ Tool ] Ensure `--dds-port=<port>` is respected when targeting web devices (flutter/flutter#174278) 2025-08-22 [email protected] Marks Mac_ios ios_debug_workflow to be unflaky (flutter/flutter#174104) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…entations. (flutter#174219) This makes two refactors to the display list architecture: * The concrete implementations of `DlRuntimeEffect` for skia and impeller are separated, and the impeller implementation put into the `impeller/display_list` target. This makes sure that a client can link against the main `display_list` library without actually pulling in all of impeller. (This is needed for flutter#172314) * The `DrawTextBlob` and `DrawTextFrame` methods are consolidated into one `DrawText` call, and that takes a `DlText` object. The `DlText` object has two implementations, one for skia and one for impeller, and the impeller one is moved into `impeller/display_list` for the same reason mentioned above.
…entations. (flutter#174219) This makes two refactors to the display list architecture: * The concrete implementations of `DlRuntimeEffect` for skia and impeller are separated, and the impeller implementation put into the `impeller/display_list` target. This makes sure that a client can link against the main `display_list` library without actually pulling in all of impeller. (This is needed for flutter#172314) * The `DrawTextBlob` and `DrawTextFrame` methods are consolidated into one `DrawText` call, and that takes a `DlText` object. The `DlText` object has two implementations, one for skia and one for impeller, and the impeller one is moved into `impeller/display_list` for the same reason mentioned above.
…entations. (flutter#174219) This makes two refactors to the display list architecture: * The concrete implementations of `DlRuntimeEffect` for skia and impeller are separated, and the impeller implementation put into the `impeller/display_list` target. This makes sure that a client can link against the main `display_list` library without actually pulling in all of impeller. (This is needed for flutter#172314) * The `DrawTextBlob` and `DrawTextFrame` methods are consolidated into one `DrawText` call, and that takes a `DlText` object. The `DlText` object has two implementations, one for skia and one for impeller, and the impeller one is moved into `impeller/display_list` for the same reason mentioned above.
…ler implementations. (flutter/flutter#174219)
…entations. (flutter#174219) This makes two refactors to the display list architecture: * The concrete implementations of `DlRuntimeEffect` for skia and impeller are separated, and the impeller implementation put into the `impeller/display_list` target. This makes sure that a client can link against the main `display_list` library without actually pulling in all of impeller. (This is needed for flutter#172314) * The `DrawTextBlob` and `DrawTextFrame` methods are consolidated into one `DrawText` call, and that takes a `DlText` object. The `DlText` object has two implementations, one for skia and one for impeller, and the impeller one is moved into `impeller/display_list` for the same reason mentioned above.
This makes two refactors to the display list architecture:
DlRuntimeEffectfor skia and impeller are separated, and the impeller implementation put into theimpeller/display_listtarget. This makes sure that a client can link against the maindisplay_listlibrary without actually pulling in all of impeller. (This is needed for [skwasm] Port toDisplayListobjects #172314)DrawTextBlobandDrawTextFramemethods are consolidated into oneDrawTextcall, and that takes aDlTextobject. TheDlTextobject has two implementations, one for skia and one for impeller, and the impeller one is moved intoimpeller/display_listfor the same reason mentioned above.