Closed Bug 1355012 Opened 7 years ago Closed 7 years ago

Add mask support for WebrenderDisplayItemLayer

Categories

(Core :: Graphics: WebRender, enhancement)

enhancement
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla55
Tracking Status
firefox55 --- fixed

People

(Reporter: ethlin, Assigned: ethlin)

References

Details

(Keywords: correctness)

Attachments

(1 file, 3 obsolete files)

Currently WebrenderDisplayItemLayer doesn't handle mask layer. It causes some reftest failures. I'll add mask layer support for WebrenderDisplayItemLayer.
Depends on: 1354464
The reftest 'layout/reftests/border-radius/iframe-1.html' is an example. When I turning on the pref 'layers.advanced.canvas-background-color', we will generate a mask layer for the DisplayItemLayer(canvas-background-color).
WebRenderLayer already has the function 'BuildWrMaskLayer', so we can just reuse the function and create a ScrollLayer for the mask. The tricky thing is WRDisplayItemLayer doesn't push transform to stacking context, so we shouldn't apply the reverse transform to mask layer. And the WR built display list doesn't support ScrollLayer[1], so I push the ScrollLayer to the base DisplayListBuilder.

[1] https://dxr.mozilla.org/mozilla-central/source/gfx/webrender_traits/src/display_list.rs#516
Attachment #8856431 - Flags: review?(mchang)
Comment on attachment 8856431 [details] [diff] [review]
apply mask in WebRenderDisplayItemLayer

Review of attachment 8856431 [details] [diff] [review]:
-----------------------------------------------------------------

::: gfx/layers/wr/WebRenderDisplayItemLayer.cpp
@@ +26,5 @@
> +    Maybe<WrImageMask> mask = BuildWrMaskLayer(gfx::Matrix4x4());
> +    if (mask.ptrOr(nullptr)) {
> +      Rect rect = TransformedVisibleBoundsRelativeToParent();
> +      Rect overflow(0.0, 0.0, rect.width, rect.height);
> +      aBuilder.PushScrollLayer(wr::ToWrRect(rect),

Why use a scroll layer instead of a stacking context? I guess we could just create a stacking context here instead since that's what all the other layers use?
Attachment #8856431 - Flags: review?(mchang) → review-
(In reply to Mason Chang [:mchang] from comment #3)
> Comment on attachment 8856431 [details] [diff] [review]
> apply mask in WebRenderDisplayItemLayer
> 
> Review of attachment 8856431 [details] [diff] [review]:
> -----------------------------------------------------------------
> 
> ::: gfx/layers/wr/WebRenderDisplayItemLayer.cpp
> @@ +26,5 @@
> > +    Maybe<WrImageMask> mask = BuildWrMaskLayer(gfx::Matrix4x4());
> > +    if (mask.ptrOr(nullptr)) {
> > +      Rect rect = TransformedVisibleBoundsRelativeToParent();
> > +      Rect overflow(0.0, 0.0, rect.width, rect.height);
> > +      aBuilder.PushScrollLayer(wr::ToWrRect(rect),
> 
> Why use a scroll layer instead of a stacking context? I guess we could just
> create a stacking context here instead since that's what all the other
> layers use?

Originally I thought scroll layer is simpler since the stacking context will change the coordinate. But it looks like scroll layer may clip other display items. I'll upload a patch with using stacking context for mask layer.
In this patch I use stacking context to do the masking. I still have to push it in base display list builder since wr_dp_push_stacking_context also push scroll layer[1].


[1] https://dxr.mozilla.org/mozilla-central/source/gfx/webrender_bindings/src/bindings.rs#1101
Attachment #8856431 - Attachment is obsolete: true
Attachment #8856847 - Flags: review?(mchang)
(In reply to Ethan Lin[:ethlin] from comment #5)
> Created attachment 8856847 [details] [diff] [review]
> apply mask in WebRenderDisplayItemLayer
> 
> In this patch I use stacking context to do the masking. I still have to push
> it in base display list builder since wr_dp_push_stacking_context also push
> scroll layer[1].

Note that pushing a scroll layer with every stacking context is probably not the right thing to be doing. I'm looking into this and trying to line up the way we push stacking contexts and scroll layers to be more correct with respect to what webrender is expecting.
Rebase the patch.
Attachment #8856847 - Attachment is obsolete: true
Attachment #8856847 - Flags: review?(mchang)
Attachment #8857384 - Flags: review?(mchang)
(In reply to Kartikaya Gupta (email:kats@mozilla.com) from comment #6)
> Note that pushing a scroll layer with every stacking context is probably not
> the right thing to be doing. I'm looking into this and trying to line up the
> way we push stacking contexts and scroll layers to be more correct with
> respect to what webrender is expecting.

Bug 1355791 does a good chunk of this.
See Also: → 1355791
Comment on attachment 8857384 [details] [diff] [review]
apply mask in WebRenderDisplayItemLayer

Review of attachment 8857384 [details] [diff] [review]:
-----------------------------------------------------------------

::: gfx/layers/wr/WebRenderDisplayItemLayer.cpp
@@ +26,5 @@
>    }
>  
> +  Maybe<WrImageMask> mask = BuildWrMaskLayer(Matrix4x4());
> +  WrImageMask* imageMask = mask.ptr();
> +  if (imageMask) {

This doesn't look right, you can only call ptr() if you know there is something inside the Maybe. You should use ptrOr(nullptr), or do |if (mask)|

@@ +58,5 @@
>    aBuilder.PushBuiltDisplayList(Move(mBuiltDisplayList));
>    WrBridge()->AddWebRenderParentCommands(mParentCommands);
> +
> +  if (imageMask) {
> +    aBuilder.PopStackingContext();

You're missing a PopScrollLayer here
(In reply to Kartikaya Gupta (email:kats@mozilla.com) from comment #9)
> Comment on attachment 8857384 [details] [diff] [review]
> apply mask in WebRenderDisplayItemLayer
> 
> Review of attachment 8857384 [details] [diff] [review]:
> -----------------------------------------------------------------
> 
> ::: gfx/layers/wr/WebRenderDisplayItemLayer.cpp
> @@ +26,5 @@
> >    }
> >  
> > +  Maybe<WrImageMask> mask = BuildWrMaskLayer(Matrix4x4());
> > +  WrImageMask* imageMask = mask.ptr();
> > +  if (imageMask) {
> 
> This doesn't look right, you can only call ptr() if you know there is
> something inside the Maybe. You should use ptrOr(nullptr), or do |if (mask)|
> 

Oh..right, I'll fix it.

> @@ +58,5 @@
> >    aBuilder.PushBuiltDisplayList(Move(mBuiltDisplayList));
> >    WrBridge()->AddWebRenderParentCommands(mParentCommands);
> > +
> > +  if (imageMask) {
> > +    aBuilder.PopStackingContext();
> 
> You're missing a PopScrollLayer here

Sorry, I will add pop function. I think I should remove stacking context since we already separated stacking context and scroll layer. And I just want do masking here. kats, Is that right?
Flags: needinfo?(bugmail)
Attachment #8857384 - Flags: review?(mchang)
(In reply to Ethan Lin[:ethlin] from comment #10)
> Sorry, I will add pop function. I think I should remove stacking context
> since we already separated stacking context and scroll layer. And I just
> want do masking here. kats, Is that right?

I think yes, you don't need the stacking context. I'm not sure you need the scroll layer either, actually. Can you not put the mask image in the existing clip region for the items? So for the example you mentioned in comment 1, where we generate a canvas background color, I think you really want the mask to be added to the clip region at [1]. But I don't know if the display item has a reference to the mask and if so, what coordinate space it's in. If you can access it there that would be the best fix I think.

[1] http://searchfox.org/mozilla-central/rev/2fc8c8d483d9ec9fd0ec319c6c53807f7fa8e8a2/layout/generic/nsCanvasFrame.cpp#322
Flags: needinfo?(bugmail)
Oh, what you could do is pass the |Maybe<WrImageMask> mask| as a parameter to CreateWebRenderCommands, and then any code inside there that creates a clip region can incorporate the mask into it.
(In reply to Kartikaya Gupta (email:kats@mozilla.com) from comment #12)
> Oh, what you could do is pass the |Maybe<WrImageMask> mask| as a parameter
> to CreateWebRenderCommands, and then any code inside there that creates a
> clip region can incorporate the mask into it.

I'm afraid it will be more complicate. I tried this solution before. But we may add multiple wr display items in CreateWebRenderCommands. Each wr item's position may have an offset to the layer, so we'll need to calculate a new mask rect for each wr item. And we also need to do above things for each gecko display items. It will be hard to test or debug if we set the mask parameters slightly incorrectly. So in the end I add a global mask in DisplayItemLayer.
Attachment #8857384 - Attachment is obsolete: true
Attachment #8857571 - Flags: review?(bugmail)
Comment on attachment 8857571 [details] [diff] [review]
apply mask in WebRenderDisplayItemLayer

Review of attachment 8857571 [details] [diff] [review]:
-----------------------------------------------------------------

I think eventually we'll want to get rid of the WebRender*Layer classes and at that point we'll probably need to push the mask into CreateWebRenderCommands anyway. I guess this is ok for now though.

::: gfx/layers/wr/WebRenderDisplayItemLayer.cpp
@@ +13,5 @@
>  #include "mozilla/gfx/Matrix.h"
>  
>  namespace mozilla {
> +
> +using namespace gfx;

Please no "using namespace". It results in unified build errors much more frequently.

::: gfx/layers/wr/WebRenderLayerManager.cpp
@@ +102,5 @@
>    return RelativeToParent(transformed);
>  }
>  
>  Maybe<WrImageMask>
> +WebRenderLayer::BuildWrMaskLayer(const gfx::Matrix4x4& aLayerTransform)

I think I would prefer if you passed in a |bool aUnapplyLayerTransform| here instead of the matrix. Inside the function you can then either do what the function was doing before (if aUnapplyLayerTransform is true) or just use an empty matrix (if aUnapplyLayerTransform is false). Not a big deal either way but I think reducing it's better to keep the number of places we're calling GetWrBoundTransform() small. More importantly it reduces the chances of an error where somebody passes in a garbage matrix.
Attachment #8857571 - Flags: review?(bugmail) → review+
Pushed by ethlin@mozilla.com:
https://hg.mozilla.org/projects/graphics/rev/3fc9e5cc78fe
Add mask layer support for WebRenderDisplayItemLayer. r=kats
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla55
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: