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

Conversation

@jonahwilliams
Copy link
Contributor

ToImage/toImageSync doesn't currently include the output of textures, due to LayerTree::Flatten using a no-op texture registry. We should provide one so texture backed platform views work.

(This implementation is just a hack so i can test it out.) Also unsure if there were other reasons why this wouldn't work

FYI @dnfield @zanderso

@jonahwilliams

This comment was marked as off-topic.

@jonahwilliams
Copy link
Contributor Author

or maybe it will, need to actually build on Android and test


sk_sp<DisplayList> LayerTree::FlattenWithContext(
const SkRect& bounds,
TextureRegistry* texture_registry) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can probably just add this as an optional parameter on Flatten

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that makes sense!

auto picture = layer_tree_->Flatten(SkRect::MakeWH(width, height));
auto picture = layer_tree_->FlattenWithContext(
SkRect::MakeWH(width, height),
snapshot_delegate.get()->GetTextureRegistry());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can drop .get() here, but you should null check this. I think if the snapshot delegate is nullptr we can just proceed without the texture registry.

Dart_Handle raw_image_handle) {
TRACE_EVENT0("flutter", "Scene::toImageSync");
auto* dart_state = UIDartState::Current();
auto snapshot_delegate = dart_state->GetSnapshotDelegate();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nullcheck on dart_state.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can be deleted now

@jonahwilliams
Copy link
Contributor Author

I got this almost working (as in, it works but eventually crashes), the problem is that the texture registry needs to be accessed on the raster thread, so the flatten call needs to go in the posted task

fml::TaskRunner::RunNowOrPostTask(
raster_task_runner,
[snapshot_delegate, unref_queue, dl_image = std::move(dl_image),
layer_tree = std::move(layer_tree.get()), width, height]() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'm doing to layer_tree doesn't seem right, but it did compile....

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can safely call takeLayerTree here. That makes the scene unusable in the future.

That said, I think we'll have to make the layer_tree_ a shared_ptr for this to work to share it across threads.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also you don't need to move a raw pointer.

You'll want something like layer_tree = layer_tree_, and make the ivar a std::shared_ptr.

@jonahwilliams jonahwilliams changed the title Hack for texture view/toImage Flatten LayerTree on raster thread to include texture registry Jul 13, 2022
@jonahwilliams jonahwilliams marked this pull request as ready for review July 13, 2022 20:57
@jonahwilliams jonahwilliams requested a review from dnfield July 13, 2022 20:57
Comment on lines 48 to 49
sk_sp<DisplayList> FlattenWithContext(const SkRect& bounds,
TextureRegistry* texture_registry);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just remove this now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oop, why did this compile lol


std::unique_ptr<flutter::LayerTree> Scene::takeLayerTree() {
return std::move(layer_tree_);
return nullptr;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing to shared_ptr almost works, except that everything that uses this API expects a unique_ptr.

Maybe I can hold onto the parts used to construct the LayerTree and then build either a shared_ptr or unique_ptr on the fly?

The root layer used to construct the layer tree is itself a shared_ptr...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's it look like to just convert all those callsites to shared?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its a lot, let me dig in some more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the PR with all the changes needed to compile this

Jonah Williams added 2 commits July 13, 2022 16:59
layer_tree = layer_tree_, width, height]() {
auto display_list =
layer_tree->Flatten(SkRect::MakeWH(width, height),
snapshot_delegate.get()->GetTextureRegistry());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need a to check snapshot_delegate. It might have been collected by now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doneish. Do I need to set anything on the dl_image, or could we assume we're shutting down now?

Copy link
Contributor

@dnfield dnfield left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will need a test.


fml::TaskRunner::RunNowOrPostTask(
raster_task_runner,
[snapshot_delegate, unref_queue, dl_image = std::move(dl_image),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::move snapshot_delegate and unref_queue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

uint32_t height,
Dart_Handle raw_image_handle);

std::shared_ptr<flutter::LayerTree> layer_tree_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider documenting why this is a shared pointer - and that it's no longer valid after takeLayerTree.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

void Scene::RasterizeToImageSync(uint32_t width,
uint32_t height,
Dart_Handle raw_image_handle) {
auto* dart_state = UIDartState::Current();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is a private method, but we should probably at least FML_DCHECK(layer_tree_) here.

Also, you'll need to do a null check on dart_state and just bail out early if it's nullptr (I think that might be extra defensive but there ends up being weirdness around isolate teardown and when these objects get destroyed).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@jonahwilliams
Copy link
Contributor Author

I added a test that Scene.toImageSync works with a texture layer, but since actual texture creation is platform specific the only way I could test it further would be to mock the texture out like the unit tests do. Any other ideas @dnfield ?

@jonahwilliams jonahwilliams requested a review from dnfield July 18, 2022 20:45
@jonahwilliams
Copy link
Contributor Author

Testing this more today, I ran into some issues I hadn't seen before with the texture registry. I'll need to step back through the code and see where I made a mistake. This doesn't block the page transition PR though, since that can use a fallback for both TextureLayer and PlatformLayer until this is fixed (we'd retain the fallback for PlatformLayer)

@jonahwilliams
Copy link
Contributor Author

Ahh I'm missing the grcontext!

@jonahwilliams jonahwilliams changed the title Flatten LayerTree on raster thread to include texture registry Flatten LayerTree on raster thread to include texture registry and GrDirectContext Jul 21, 2022
@jonahwilliams
Copy link
Contributor Author

Updated and works correctly now, we also need a GrContext to paint the texture


sk_sp<DisplayList> LayerTree::Flatten(const SkRect& bounds) {
sk_sp<DisplayList> LayerTree::Flatten(const SkRect& bounds,
TextureRegistry* texture_registry,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In #35073 I'm making this a shared_ptr everywhere. Could you rebase on top of that? I'd rather do that than have bare pointers floating around.


sk_sp<DisplayList> Flatten(const SkRect& bounds);
sk_sp<DisplayList> Flatten(const SkRect& bounds,
TextureRegistry* texture_registry = nullptr,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto here - let's just make these smart pointer objects.

}
return _futurize((_Callback<Image?> callback) => _toImage(width, height, (_Image? image) {
final _Image image = _Image._();
return _futurize((_Callback<Image?> callback) => _toImage(width, height, image, (_Image? image) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should just make this a voidcallback, right?

We're passing in an image and then passing the same handle back it seems.

@jonahwilliams
Copy link
Contributor Author

Will update this after I can rebase on the toPictureSync change

@jonahwilliams
Copy link
Contributor Author

I think we should probably icebox this until we figure out toImageSync for Image shaders/paints.

Otherwise we'll end up with different coverage on the sync and async paths, with the former able to access textures easily and the latter able to be used in image shaders

@jonahwilliams jonahwilliams deleted the hack_for_texture_view branch August 10, 2022 17:53
@jonahwilliams jonahwilliams restored the hack_for_texture_view branch August 17, 2022 07:16
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants