-
Notifications
You must be signed in to change notification settings - Fork 6k
[embedder] embedder external view adopt DisplayListEmbedderViewSlice #40578
Conversation
| auto dl_canvas = std::make_unique<DlSkCanvasAdapter>(canvas); | ||
| int restore_count = dl_canvas->GetSaveCount(); | ||
| dl_canvas->SetTransform(surface_transformation_); | ||
| dl_canvas->Clear(SK_ColorTRANSPARENT); |
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.
Technically, while SK_Color constants are automatically interchangeable with DlColor instances (they both just boil down to a uint32_t), It would be better to use DlColor::kTransparent() here to continue the theme of non-skia use while talking to Dl objects.
34b2609 to
f73d8cd
Compare
|
@flar This is ready to be reviewed! |
e4fb81f to
e0f867c
Compare
ci/licenses_golden/licenses_flutter
Outdated
| ORIGIN: ../../../flutter/display_list/dl_op_receiver.h + ../../../flutter/LICENSE | ||
| ORIGIN: ../../../flutter/display_list/dl_op_records.cc + ../../../flutter/LICENSE | ||
| ORIGIN: ../../../flutter/display_list/dl_op_records.h + ../../../flutter/LICENSE | ||
| ORIGIN: ../../../flutter/display_list/dl_op_spy.cc + ../../../flutter/LICENSE |
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 there a need to add these files to the display_list code? The mechanism is only used by one "client" module of DL and isn't generally something that developers query about their display lists. I provided the general utilities in this package (such as the Ignore classes) to help with implementing OpReceiver classes, with the intention that other modules or packages could roll their own for their own purposes.
For example, Impeller processes OpReceiver streams using a class that lives in their source hierarchy.
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 initially put it in the platform/embedder/ but saw canvas_spy is in /common, so I thought maybe this class should be in a common place.
Do you have a preference where it should be?
display_list/BUILD.gn
Outdated
| ":display_list_fixtures", | ||
| "//flutter/display_list/testing:display_list_testing", | ||
| "//flutter/testing", | ||
| "//third_party/skia", |
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.
Why is this needed? I'm guessing if the spy stuff gets moved out of here into the embedder source directories then it doesn't need to be added here, but I would have thought that you could implement an OpReceiver without having to add this dependency...?
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.
This is for the unittest, to generate a concrete DlImage for testing.
display_list/dl_op_spy.cc
Outdated
|
|
||
| namespace flutter { | ||
|
|
||
| bool DlOpSpy::DidDraw() { |
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've been using lower case for getters which I think is compliant with the style guidelines - did_draw()...
| } | ||
| } | ||
| void DlOpSpy::setColorSource(const DlColorSource* source) { | ||
| const DlColorColorSource* color_source = source->asColor(); |
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.
What if source is null?
display_list/dl_op_spy.cc
Outdated
| if (did_draw_) { | ||
| return; | ||
| } | ||
| did_draw_ = dirty_ && p0 != p1; |
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.
p0 == p1 draws something
display_list/dl_op_spy.cc
Outdated
| if (did_draw_) { | ||
| return; | ||
| } | ||
| did_draw_ = !color.isTransparent() && elevation > 0 && !path.isEmpty(); |
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'm not sure about elevation == 0. I think it might also depend on transparent_occluder as well.
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.
what does transparent_occluder do?
display_list/dl_op_spy.h
Outdated
| class DlOpSpy final : public IgnoreAttributeDispatchHelper, | ||
| public IgnoreClipDispatchHelper, | ||
| public IgnoreTransformDispatchHelper, | ||
| public IgnoreDrawDispatchHelper { |
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.
Does this compile without inheriting from IgnoreDraw? I think you probably cover all of the draw commands yourself.
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 are still calls in ignoreDraw: save, savelayer, restore.
flow/embedded_views.cc
Outdated
| } | ||
|
|
||
| bool DisplayListEmbedderViewSlice::recording_ended() { | ||
| return recording_ended_; |
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.
This could also be deduced from display_list_ being non-null or builder_ being null.
| return canvas_spy_->DidDrawIntoCanvas(); | ||
| TryEndRecording(); | ||
| slice_->dispatch(*dl_op_spy_); | ||
| return dl_op_spy_->DidDraw() && !slice_->is_empty(); |
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.
If this method is called more than once it will repeat the op_spy operation. Also, it will re-use the op_spy object which means the second answer might not be correct. I would change this so that it only does the spy operation once and remembers the answer.
Also, you don't need to permanently store an op_spy object, just create one on the fly when you need to compute the answer and remove the dl_op_spy field from the object.
| std::unique_ptr<SkPictureRecorder> recorder_; | ||
| std::unique_ptr<CanvasSpy> canvas_spy_; | ||
| std::unique_ptr<DisplayListEmbedderViewSlice> slice_; | ||
| std::unique_ptr<DlOpSpy> dl_op_spy_; |
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.
You only need dl_op_spy for the short time when you are computing the answer. It can be created on the stack in that method.
|
@flar Updated per review comments and offline discussions. PTAL. |
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.
Minor edits suggested, but the basic concept is good.
shell/common/dl_op_spy.h
Outdated
| /// on the canvas. | ||
| /// All the drawImage operations are considered drawing non-transparent pixels. | ||
| /// | ||
| /// To use this class, dispatching the operations from DisplayList to a concrete |
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.
dispatching => dispatch
shell/common/dl_op_spy.h
Outdated
| class DlOpSpy final : public IgnoreAttributeDispatchHelper, | ||
| public IgnoreClipDispatchHelper, | ||
| public IgnoreTransformDispatchHelper, | ||
| public IgnoreDrawDispatchHelper { |
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 you want to ignore any Draw calls, I'd remove the IgnoreDraw inheritance to make sure you've implemented all of them.
Also, since you are intending for DlOpSpy to implement DlOpReceiver, that should be your first public inheritance even though you get it indirectly from any or all of the Ignore classes you inherit from - it's good to explicitly document that this class is first and foremost intending to be a Receiver (and the rest of the inheritance clauses are just implementation details).
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.
So:
class DlOpSpy final : public DlOpReceiver,
public IgnoreAttributeDispatchHelper,
public IgnoreClipDispatchHelper,
public IgnoreTransformDispatchHelper {
And if this works without the public inheritance from the Ignore classes that might indicate the purpose even better, as in:
class DlOpSpy final : public DlOpReceiver,
IgnoreAttributeDispatchHelper,
IgnoreClipDispatchHelper,
IgnoreTransformDispatchHelper {
(I realize we aren't consistent about this in other places, but we probably should be)
shell/common/dl_op_spy.h
Outdated
| bool transparent_occluder, | ||
| SkScalar dpr) override; | ||
|
|
||
| // Whether there is a color set before drawing and the last color set is not |
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 simplify the comment to
"Indicates if the attributes are set to values that will modify the destination. For now, the test only checks if there is a non-transparent color set."
and maybe change the name to "will_draw_"?
shell/common/dl_op_spy.cc
Outdated
| did_draw_ |= dirty_; | ||
| } | ||
| void DlOpSpy::drawPath(const SkPath& path) { | ||
| if (did_draw_) { |
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.
This test seems out of place compared to the other draw methods. If some complicated operation on path was being saved, then it might make sense, but is there a reason why it doesn't just use did_draw_ |= dirty_ like the rest?
shell/common/dl_op_spy.cc
Outdated
| const SkScalar elevation, | ||
| bool transparent_occluder, | ||
| SkScalar dpr) { | ||
| if (did_draw_) { |
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.
Same as with drawPath, is this saving enough work to justify an early return? This method is very much like drawColor and should have a similar implementation.
| kTrue, | ||
| kFalse, | ||
| }; | ||
| HasEngineRenderedContentResult has_engine_rendered_contents_ = |
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.
This could also be std::optional<bool>?
|
auto label is removed for flutter/engine, pr: 40578, due to - The status or check suite Linux Framework Smoke Tests has failed. Please fix the issues identified (or deflake) before re-applying this label. |
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.
Reiterating LGTM after review updates...
43a59ab to
478b99b
Compare
478b99b to
a0e6b88
Compare
…lutter#40578) [embedder] embedder external view adopt DisplayListEmbedderViewSlice
Adopt
DisplayListEmbedderViewSlicein EmbedderExternalViewFixes flutter/flutter#123349
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.