Skip to content
This repository was archived by the owner on Apr 29, 2022. It is now read-only.

Filters: Add local transforms#140

Merged
bdero merged 4 commits intoflutter:mainfrom
bdero:bdero/filter-local-transforms
Apr 21, 2022
Merged

Filters: Add local transforms#140
bdero merged 4 commits intoflutter:mainfrom
bdero:bdero/filter-local-transforms

Conversation

@bdero
Copy link
Contributor

@bdero bdero commented Apr 16, 2022

This is a refactor to add support for local transforms in FilterContents, which sets us up for adding flexible filter elision behavior and TransformFilters.

  • FilterContents:

    • Add a virtual method that computes the local transform.
    • Have filter-specific virtual methods (RenderFilter and GetFilterCoverage) always receive the entity with the local transform already pre-applied, so that filter implementations don't have to worry about dealing with it. We pass the whole entity around instead of a separate transform because many Contents use other entity fields (i.e. the path) for computing coverage. Also, TextureFilterInput uses the path for computing the local transform, which is incorporated when computing coverage.
    • Pass const ref of the inputs to GetFilterCoverage.
  • FilterInput:

    • Subclass FilterInput (as opposed to dispatching with branches based on the variant input). It felt like the right time to do this since we're now up to 3 variants, and each of them are quite unique in their behavior.
    • Add a specialized FilterContents input variant which respects the local transform of filters.
    • Add GetTransform / GetLocalTransform virtual methods that behave reasonably for each variant.
  • Gaussian image/mask blurs: Use the first input's transform for computing the blur's influence on coverage.

return std::nullopt;
}

auto coverage = inputs[0]->GetCoverage(entity);
Copy link
Contributor

Choose a reason for hiding this comment

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

here and on the guassian filter below: why are we only using the first input? Do we expect there to only ever be one?

It seems confusing to me that this API sometimes takes and uses multiple vector inputs and other times only uses one.

Copy link
Contributor Author

@bdero bdero Apr 21, 2022

Choose a reason for hiding this comment

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

This funkiness is a side effect of making filter inputs agnostic to the filter implementation (partly inspired by the design of Core Image).

This detail used to be more important because FilterContents would resolve all the filter inputs as textures before calling the render method, but that work is now deferred through FilterInputs. There's still a default coverage routine that most filters won't need to override in practice, but that's been majorly simplified now that everything has a GetCoverage, including FilterInput itself.

Creating Filters in Impeller is locked down to static factory methods in FilterContents that take the intended number of inputs. In the filters themselves, too many inputs isn't an error, but not enough inputs fails the render.

At this point I'm not really married to this detail, but keeping it around might make creating a debug view for filters easier. 🤷 We can probably remove it sometime and make specific SetInputs methods on the filter implementations themselves since it's not really important anymore.

Copy link
Contributor

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

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

LGTM pending Dan's query. Everything else is nits or can be tackled in a later patch. I really like this approach.

/// Filters may decide to not evaluate inputs in situations where they won't
/// contribute to the filter's output texture.
class FilterInput final {
class FilterInput {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: The headerdoc comments above are now out of date.

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.


virtual std::optional<Rect> GetCoverage(const Entity& entity) const = 0;

virtual Matrix GetLocalTransform(const Entity& entity) const;
Copy link
Contributor

Choose a reason for hiding this comment

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

A brief explanation in a headerdoc of the differences between a local transform and the transform would be good.

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.

if (auto texture = std::get_if<std::shared_ptr<Texture>>(&input_)) {
return entity.GetPathCoverage();
}
/*******************************************************************************
Copy link
Contributor

Choose a reason for hiding this comment

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

In a later patch if necessary, you could toss these in their own TUs (perhaps in a "filters" directory).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yeah, I'll do this in a follow-up since #145 changes a bunch of stuff in FilterInput.

entity/entity.h Outdated
~Entity();

/// @brief Make a copy of this entity, but with a different transform.
Entity WithTransform(const Matrix& transform) const;
Copy link
Contributor

Choose a reason for hiding this comment

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

On the fence with this one. Seems like a utility method that provides very little utility. But, your call TBH.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Eh, I don't have a very strong opinion. Removed it.

@bdero bdero force-pushed the bdero/filter-local-transforms branch from e1f636d to b9ebbde Compare April 21, 2022 02:15
@bdero bdero merged commit f1d5524 into flutter:main Apr 21, 2022
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.

3 participants