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

Remove Path member from Entity; have Contents source user-supplied geometry when applicable instead#145

Merged
bdero merged 1 commit intoflutter:mainfrom
bdero:bdero/untie-paths-from-entities
Apr 21, 2022
Merged

Remove Path member from Entity; have Contents source user-supplied geometry when applicable instead#145
bdero merged 1 commit intoflutter:mainfrom
bdero:bdero/untie-paths-from-entities

Conversation

@bdero
Copy link
Contributor

@bdero bdero commented Apr 19, 2022

Built on top of changes in #140.

Contents are ultimately responsible for sourcing the geometry to use for rendering, and so Path usage is turning out to be a close implementation detail for specific Contents rather than general data that we need access to everywhere.

Friction addressed by this:

  • Path is not the only kind of user geometry that we need to support for all of the "paint" operations, we also need to support user-supplied Vertices (by either extending existing Contents or creating new Contents that accept Vertices instead of a Path when applicable).
  • There are a growing number of cases where user-provided geometry is not necessary (we normally throw around empty paths for these cases and ignore it). The following Contents don't require Paths:
    • ClearContents
    • TextContents
    • FilterContents and all filter implementations
    • ClipRestoreContents

I decided to try going this route while thinking through drawVertices, and it turned out to be a pretty natural refactor that makes a lot of code slightly less weird! This change also makes mistakes computing coverage less likely, as it's very tempting to just grab the entity path coverage, even when the path is unused/doesn't make any sense for the Contents (although we should be free of coverage bugs after all the recent coverage-related change).

Also also, now that everything is computing coverage correctly, I removed the default GetCoverage implementation. A bunch of the Contents just use their path coverage right now, but this will change down the road as we start supporting Vertices.

@bdero bdero changed the title WIP: Make paths associated with contents rather than entities. Remove Path member from Entity; have Contents source user-supplied geometry when applicable instead Apr 19, 2022
@bdero bdero requested review from chinmaygarde, dnfield and flar and removed request for chinmaygarde and flar April 19, 2022 22:55
@bdero bdero force-pushed the bdero/untie-paths-from-entities branch from 3ac42fa to cb259e7 Compare April 19, 2022 23:14

~ClipContents();

void SetPath(Path path);
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 below:

This seems like it should be a virtual method on Contents.

It also seems like it would be better to have a method like SetGeometry that takes some kind of virtual object that can be tessellated. For paths this would use the tessellator. For vertices it would just return the vertex/index buffers.

One thing that might make drawVertices a little more complicated is when there are color and/or texture coordinates. That doesn't have to be handled here though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This seems like it should be a virtual method on Contents.

This would be mostly the same as keeping it as a method on Entity. Often times we don't really need any geometry, and the type of geometry we need is sort of an implementation detail of the Contents.

In general, I think the specific Contents implementation needs to ultimately decide how it's going to source and render its geometry. If we try to have a catch-all parameter, it'll end up getting unused/worked around most of the time (which is the current state of affairs).

Something to note here is that strokes and fills aren't the only cases where we need to perform path-based geometry generation. For example, we will likely end up having a Contents that renders shadows by generating inset/outset geometry. The implementation changes depends on whether the path crosses over itself, and the specifics of the technique we use will depend on whether the Path contours are fully convex or not -- we should probably get this info from the Path object itself, and so it seems like a generic Geometry object would end up being worked around/redundant here.

It also seems like it would be better to have a method like SetGeometry that takes some kind of virtual object that can be tessellated. For paths this would use the tessellator. For vertices it would just return the vertex/index buffers.

In some Contents, we'll probably wanna combine things/handle this branching inline. For that, I was planning to just do SetGeometry(std::variant<Path, Vertices>) in contents where it makes sense.

Having an intermediary object that's responsible for outputting the geometry was something I considered, but I ended up stepping back and going this route because it doesn't make combining Contents any easier. We'd still have to have a branch that handles Vertices output separately from the "tessellated Path" output. The specific way we'll need to normalize the vertex data depends on what what exactly needs to be rendered (which is decided through the previous setColorSource call).
For example: If the source type is a "color" and drawVertices is called, we copy the vertex colors in (or fallback to the paint color if no vertex colors are given); if a drawPath-like is called, we always just use the paint color. drawVetices uses either the SolidColorPipeline or VertexColorPipeline, and drawPath (the more common case), ends up always using SolidColorPipeline.

In more complicated cases, I'd like to retain the flexibility to just implement the different cases as totally separate Contents if need be -- we'd still be able to do that with a generic geometry parameter everywhere, but it wouldn't be possible to know what the Contents actually accepts based on the API this way.

Copy link
Contributor

Choose a reason for hiding this comment

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

So should these classes have Path in the name, and we'll have a new type of Contents entirely for vertices?

I'm not a huge fan of std::variant. I imagine we'd end up having code that looks something like

  switch (geometry_content_type) {
    case Path: // tessellate a path using a special method that knows how to deal with paths
    case Vertices: // use a different special method that knows how to deal with vertices
  }

Which will bloat up the class and likely require duplicated logic elsewhere.

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, I'm not against having separate minimal Contents for each of the Path and Vertices paint situations just to keep it simple. I think they'll all end up being very straight forward and not have very much shared stuff (apart from parameters and maybe uniform bindings for the gradients). They're even small enough to justify maybe placing them next to their complements in the same TUs.

In total, we need to cover each of these color sources for both Paths and Vertices:

  • kColor
  • kLinearGradient
  • kImage
  • kRadialGradient
  • kConicalGradient
  • kSweepGradient

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok. In that case, does it make sense to rename this to something like FooPathContents to make that clear? Either way, LGTM.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Argh, sorry, I didn't see this message before I merged. Yes, I think that makes sense -- I will follow up and normalize these names a bit when adding the Vertices case for kColor.

Copy link
Contributor

Choose a reason for hiding this comment

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

No worries, fine to handle in a follow up or decide against it. Shouldn't hold anything up

@bdero bdero force-pushed the bdero/untie-paths-from-entities branch from cb259e7 to 09efcf0 Compare April 21, 2022 02:27
@bdero bdero requested a review from dnfield April 21, 2022 18:49
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