Skip to content
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

Need API to set a composition operator that's not "over" #1416

Closed
mstange opened this issue Jun 21, 2017 · 10 comments
Closed

Need API to set a composition operator that's not "over" #1416

mstange opened this issue Jun 21, 2017 · 10 comments

Comments

@mstange
Copy link
Contributor

@mstange mstange commented Jun 21, 2017

Webrender currently supports MixBlendModes, but all the modes in this list don't affect the destination alpha. In Gecko we also need the modes Clear and Destination Out. Ideally we'd have all the porter duff modes so that we can support the whole list of Moz2D CompositionOp values.

We have two cases where we need this, and both of them are about native appearance on Mac.

  1. We need to clear the background behind vibrant regions, e.g. behind the bookmarks sidebar. In Gecko we do that using a ColorLayer whose color is transparent black and whose composition op is OP_SOURCE. But it could just as well use OP_CLEAR.
  2. We round the window corners by painting four small images in the corners with OP_DEST_OUT. This causes the destination pixels outside of the rounded shape to become transparent.
bors-servo added a commit that referenced this issue Jul 19, 2017
tiling: derive Default for CompositeOps.

I was poking at #1416, and found this while at it.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1499)
<!-- Reviewable:end -->
bors-servo added a commit that referenced this issue Jul 19, 2017
tiling: derive Default for CompositeOps.

I was poking at #1416, and found this while at it.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1499)
<!-- Reviewable:end -->
@mstange
Copy link
Contributor Author

@mstange mstange commented Oct 6, 2017

@glennw There's one aspect of this that may be worth thinking about as part of #1774:

For optimal performance with operator source, the concept of "opaqueness" may need to be split into two dimensions. If you draw something with operator source, the old values of the destination pixels get completely ignored and replaced. So you'll want to cull any primitives underneath anything that's drawn with operator source, because anything that was drawn underneath has no impact on the final rendering anyway. However, after drawing the operator source item, the affected pixels may be transparent, and for example any text that is drawn directly on top will not be able to use subpixel AA.

The same applies to operator clear.

So there's a difference between "opaque in the sense that items underneath can be culled", and "opaque in the sense that items on top will draw to opaque pixels". Just something to be aware of.

@kvark
Copy link
Member

@kvark kvark commented Oct 19, 2017

However, after drawing the operator source item, the affected pixels may be transparent, and for example any text that is drawn directly on top will not be able to use subpixel AA.

I'm having trouble understanding this part. Why would a primitive care about what's drawn on top of it?
In general, the current difference in handling opaque vs transparent is because the latter depends on what's drawn below it, not on top.

@mstange
Copy link
Contributor Author

@mstange mstange commented Oct 19, 2017

The primitive itself does not care about what is drawn on top of it. But the rendering system as a whole does. In general, some decisions about a given item depend on the type of items underneath it, and some depend on the type of items on top of it.

More specifically, if the question is "Do I have to render item $X?", the answer is "Not if there's an opaque element with operator OVER on top of it, or if there's any element with operator SOURCE on top of it." And if the question is "Can I use subpixel AA for the text item $Y?", then the answer is "Not if there's an operator SOURCE item underneath it that's not opaque (unless there is another opaque element in between).".

@mstange
Copy link
Contributor Author

@mstange mstange commented Oct 23, 2017

I have a naive implementation of this. It adds a composition_op to the API in the same place that backface_visible was added, so it applies to everything. This is perhaps a bit much; all I really need is the ability to clear rectangles, and to draw small images with operator destination-in. So there may exist a better API for this. For example, for rounded borders, operator source isn't really meaningful - it probably applies to the bounding rectangle of the border, and maybe that's what you'd expect, but maybe it's not.

It seems to be working well; I now have working vibrancy and rounded bottom corners. The text on top of vibrancy doesn't render the way it should, but that's expected.

@glennw
Copy link
Member

@glennw glennw commented Oct 23, 2017

I do agree that we probably want a simpler API for this, since it's such a niche use case in WR. How about a post-processing API which can apply a list of screen-aligned rectangles with a mask + composition operator?

@mstange
Copy link
Contributor Author

@mstange mstange commented Oct 23, 2017

For the rectangle-clearing use case, the order with respect to the other display items is important. For example, at the moment, our browser chrome on macOS has elements in this order:

  1. The window's background color.
  2. A native toolbar with a gradient. This gradient ends up being invisible and really only exists because it is used to give other parts of the Firefox platform a hint about where to position sheet windows (they get positioned at the bottom edge of the "main toolbar" of a window).
  3. The rectangle that clears the tab bar background.
  4. The tabs themselves, with favicons and text.

So the rectangle needs to be cleared after 2 but before 4.

@glennw
Copy link
Member

@glennw glennw commented Oct 23, 2017

Ah, makes sense. I wonder if a specific primitive type might make sense then?

@mstange
Copy link
Contributor Author

@mstange mstange commented Oct 23, 2017

Sounds good to me.

For the other use case (rounding the window corners), maybe the API should be just that: Give WebRender an API that lets you specify a BorderRadius struct for the root frame buffer, and then WebRender itself can decide how to apply that root clip. It may still decide to use the destination-in blend mode with four small rounded images to do that.

@glennw
Copy link
Member

@glennw glennw commented Oct 23, 2017

Yep, that sounds good.

@mstange
Copy link
Contributor Author

@mstange mstange commented Oct 24, 2017

I've filed #1926 and #1927 about the smaller APIs. I'm going to close this issue since we don't need the full freedom of arbitrary compositing operators at the moment.

@mstange mstange closed this Oct 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.