Bug 95258

Summary: Add support for blendmode to webkit rendering engine
Product: WebKit Reporter: Rik Cabanier <cabanier>
Component: CSSAssignee: Nobody <webkit-unassigned>
Status: RESOLVED FIXED    
Severity: Normal CC: cmarcelo, dino, eric, macpherson, menard, simon.fraser, webkit.review.bot
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on:    
Bug Blocks: 91908    
Attachments:
Description Flags
First try
simon.fraser: review-, simon.fraser: commit-queue-
added test that checks for compositing layer. Removed test from RenderLayerCompositor.cpp. Added helper function that tests for mask, filter and blend.
none
renamed function so it's shorter
simon.fraser: review-, simon.fraser: commit-queue-
updated all places where requiresLayer checked. Added comment + moved function to public declaration. Changed compositor so it call public function
simon.fraser: review+, simon.fraser: commit-queue-
changed the test file so it uses a <pre> instead of a <div> none

Description Rik Cabanier 2012-08-28 16:07:03 PDT
This patch will add support for blendmode to the WebCore engine.
A later patch will add support for CoreAnimation and Chromium
Comment 1 Rik Cabanier 2012-08-28 16:49:13 PDT
Created attachment 161090 [details]
First try
Comment 2 Rik Cabanier 2012-08-28 18:37:07 PDT
No tests since the rendering and parsing didn't change
Comment 3 Simon Fraser (smfr) 2012-08-29 11:06:50 PDT
Comment on attachment 161090 [details]
First try

View in context: https://bugs.webkit.org/attachment.cgi?id=161090&action=review

> Source/WebCore/ChangeLog:12
> +        No new tests (OOPS!).

OOPS

This patch does change behavior: it makes compositing layers for blending, so this should be tested.

> Source/WebCore/rendering/RenderInline.h:128
> +    virtual bool requiresLayer() const { return isInFlowPositioned() || isTransparent() || hasMask() || hasFilter() || hasBlendMode(); }

It might be worth making a method on RenderObject for hasMask() || hasFilter() || hasBlendMode(), since these all have similar effects.

> Source/WebCore/rendering/RenderLayerBacking.cpp:963
>  {
> -    return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
> +    return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter() || style->hasBlendMode();
>  }

I'm not sure this is correct. We use hasBoxDecorations() to tell if we need backing store, but I don't think the blend mode needs to affect that answer.

> Source/WebCore/rendering/RenderLayerCompositor.cpp:1484
> +        || renderer->hasBlendMode())

Again, not sure if this is true for all platforms. I don't think we need backing store for CA to do blending.
Comment 4 Rik Cabanier 2012-08-29 12:54:52 PDT
Created attachment 161292 [details]
added test that checks for compositing layer. Removed test from RenderLayerCompositor.cpp. Added helper function that tests for mask, filter and blend.
Comment 5 Rik Cabanier 2012-08-29 13:07:03 PDT
(In reply to comment #3)
> (From update of attachment 161090 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=161090&action=review
> 
> > Source/WebCore/ChangeLog:12
> > +        No new tests (OOPS!).
> 
> OOPS
> 
> This patch does change behavior: it makes compositing layers for blending, so this should be tested.

I added a test to the patch

> 
> > Source/WebCore/rendering/RenderInline.h:128
> > +    virtual bool requiresLayer() const { return isInFlowPositioned() || isTransparent() || hasMask() || hasFilter() || hasBlendMode(); }
> 
> It might be worth making a method on RenderObject for hasMask() || hasFilter() || hasBlendMode(), since these all have similar effects.

I added a helper method to RenderObject.

> 
> > Source/WebCore/rendering/RenderLayerBacking.cpp:963
> >  {
> > -    return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
> > +    return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter() || style->hasBlendMode();
> >  }
> 
> I'm not sure this is correct. We use hasBoxDecorations() to tell if we need backing store, but I don't think the blend mode needs to affect that answer.

You were right. This wasn't needed.

> 
> > Source/WebCore/rendering/RenderLayerCompositor.cpp:1484
> > +        || renderer->hasBlendMode())
> 
> Again, not sure if this is true for all platforms. I don't think we need backing store for CA to do blending.

I verified that it was needed in this case. Blending is just like opacity so it should follow the same logic.
Comment 6 Simon Fraser (smfr) 2012-08-29 14:23:02 PDT
Comment on attachment 161292 [details]
added test that checks for compositing layer. Removed test from RenderLayerCompositor.cpp. Added helper function that tests for mask, filter and blend.

View in context: https://bugs.webkit.org/attachment.cgi?id=161292&action=review

> Source/WebCore/rendering/RenderObject.h:943
> +    bool hasEffectThatNeedsLayer() const { return hasMask() || hasFilter() || hasBlendMode(); } 

I think this name is a bit literal. Maybe hasGraphicalEffect() or something? Is there generic name in graphics for these treatments that require that descendants need to be pre-rendered?
Comment 7 Rik Cabanier 2012-08-29 14:36:36 PDT
(In reply to comment #6)
> (From update of attachment 161292 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=161292&action=review
> 
> > Source/WebCore/rendering/RenderObject.h:943
> > +    bool hasEffectThatNeedsLayer() const { return hasMask() || hasFilter() || hasBlendMode(); } 
> 
> I think this name is a bit literal. Maybe hasGraphicalEffect() or something? Is there generic name in graphics for these treatments that require that descendants need to be pre-rendered?

That would be a 'group' (aka a layer)
Should I rename it to graphicalEffectNeedsGroup()?
Comment 8 Simon Fraser (smfr) 2012-08-29 14:38:16 PDT
(In reply to comment #7)
> (In reply to comment #6)
> > (From update of attachment 161292 [details] [details])
> > View in context: https://bugs.webkit.org/attachment.cgi?id=161292&action=review
> > 
> > > Source/WebCore/rendering/RenderObject.h:943
> > > +    bool hasEffectThatNeedsLayer() const { return hasMask() || hasFilter() || hasBlendMode(); } 
> > 
> > I think this name is a bit literal. Maybe hasGraphicalEffect() or something? Is there generic name in graphics for these treatments that require that descendants need to be pre-rendered?
> 
> That would be a 'group' (aka a layer)
> Should I rename it to graphicalEffectNeedsGroup()?

hasGroupEffect()?
createsGroup()?
Comment 9 Rik Cabanier 2012-08-29 14:40:39 PDT
(In reply to comment #8)
> (In reply to comment #7)
> > (In reply to comment #6)
> > > (From update of attachment 161292 [details] [details] [details])
> > > View in context: https://bugs.webkit.org/attachment.cgi?id=161292&action=review
> > > 
> > > > Source/WebCore/rendering/RenderObject.h:943
> > > > +    bool hasEffectThatNeedsLayer() const { return hasMask() || hasFilter() || hasBlendMode(); } 
> > > 
> > > I think this name is a bit literal. Maybe hasGraphicalEffect() or something? Is there generic name in graphics for these treatments that require that descendants need to be pre-rendered?
> > 
> > That would be a 'group' (aka a layer)
> > Should I rename it to graphicalEffectNeedsGroup()?
> 
> hasGroupEffect()?
> createsGroup()?

createsGroup sounds good. needsGroup would be good too
Comment 10 Rik Cabanier 2012-08-29 15:19:52 PDT
Created attachment 161330 [details]
renamed function so it's shorter
Comment 11 Simon Fraser (smfr) 2012-08-29 15:54:21 PDT
Comment on attachment 161330 [details]
renamed function so it's shorter

View in context: https://bugs.webkit.org/attachment.cgi?id=161330&action=review

> Source/WebCore/rendering/RenderBoxModelObject.h:90
> +    virtual bool requiresLayer() const { return isRoot() || isPositioned() || isTransparent() || hasTransform() || hasHiddenBackface() || hasReflection() || createsGroup() || style()->specifiesColumns(); }

You also need to change RenderBox::requiresLayer() and RenderTableRow::requiresLayer().

> Source/WebCore/rendering/RenderLayerCompositor.cpp:1780
> +    if (hasCompositedDescendants && (layer->transform() || renderer->isTransparent() || renderer->hasMask() || renderer->hasReflection() || renderer->hasFilter() || renderer->hasBlendMode())) {
>          reason = RenderLayer::IndirectCompositingForGraphicalEffect;

Why not use createsGroup() here?

> Source/WebCore/rendering/RenderObject.h:943
> +    bool createsGroup() const { return hasMask() || hasFilter() || hasBlendMode(); } 

I think this deserves a comment explaining the usage of "group". Should isTransparent() also be included?
Comment 12 Rik Cabanier 2012-08-29 16:32:14 PDT
(In reply to comment #11)
> (From update of attachment 161330 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=161330&action=review
> 
> > Source/WebCore/rendering/RenderBoxModelObject.h:90
> > +    virtual bool requiresLayer() const { return isRoot() || isPositioned() || isTransparent() || hasTransform() || hasHiddenBackface() || hasReflection() || createsGroup() || style()->specifiesColumns(); }
> 
> You also need to change RenderBox::requiresLayer() and RenderTableRow::requiresLayer().
> 
> > Source/WebCore/rendering/RenderLayerCompositor.cpp:1780
> > +    if (hasCompositedDescendants && (layer->transform() || renderer->isTransparent() || renderer->hasMask() || renderer->hasReflection() || renderer->hasFilter() || renderer->hasBlendMode())) {
> >          reason = RenderLayer::IndirectCompositingForGraphicalEffect;
> 
> Why not use createsGroup() here?
> 
> > Source/WebCore/rendering/RenderObject.h:943
> > +    bool createsGroup() const { return hasMask() || hasFilter() || hasBlendMode(); } 
> 
> I think this deserves a comment explaining the usage of "group". Should isTransparent() also be included?

yes, I will add that. hasTransform seems like it should be added as well, except that RenderInline does not check for that. Is it because inline is never transformed?
Comment 13 Rik Cabanier 2012-08-29 16:46:42 PDT
Created attachment 161359 [details]
updated all places where requiresLayer checked. Added comment + moved function to public declaration. Changed compositor so it call public function
Comment 14 Simon Fraser (smfr) 2012-08-29 17:16:16 PDT
Comment on attachment 161359 [details]
updated all places where requiresLayer checked. Added comment + moved function to public declaration. Changed compositor so it call public function

View in context: https://bugs.webkit.org/attachment.cgi?id=161359&action=review

> LayoutTests/css3/compositing/should-have-compositing-layer.html:30
> +<div id="layertree"></div>

Best to use a <pre> for this so that indentation is maintained.
Comment 15 Rik Cabanier 2012-08-29 20:09:50 PDT
Created attachment 161391 [details]
changed the test file so it uses a <pre> instead of a <div>
Comment 16 WebKit Review Bot 2012-08-29 20:56:47 PDT
Comment on attachment 161391 [details]
changed the test file so it uses a <pre> instead of a <div>

Rejecting attachment 161391 [details] from commit-queue.

cabanier@adobe.com does not have committer permissions according to http://trac.webkit.org/browser/trunk/Tools/Scripts/webkitpy/common/config/committers.py.

- If you do not have committer rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags.

- If you have committer rights please correct the error in Tools/Scripts/webkitpy/common/config/committers.py by adding yourself to the file (no review needed).  The commit-queue restarts itself every 2 hours.  After restart the commit-queue will correctly respect your committer rights.
Comment 17 WebKit Review Bot 2012-08-29 22:21:10 PDT
Comment on attachment 161391 [details]
changed the test file so it uses a <pre> instead of a <div>

Rejecting attachment 161391 [details] from commit-queue.

Failed to run "['/mnt/git/webkit-commit-queue/Tools/Scripts/webkit-patch', '--status-host=queues.webkit.org', '-..." exit_code: 1

ERROR: /mnt/git/webkit-commit-queue/LayoutTests/ChangeLog neither lists a valid reviewer nor contains the string "Unreviewed" or "Rubber stamp" (case insensitive).

Full output: http://queues.webkit.org/results/13684555
Comment 18 WebKit Review Bot 2012-08-30 11:02:29 PDT
Comment on attachment 161391 [details]
changed the test file so it uses a <pre> instead of a <div>

Clearing flags on attachment: 161391

Committed r127162: <http://trac.webkit.org/changeset/127162>
Comment 19 WebKit Review Bot 2012-08-30 11:02:35 PDT
All reviewed patches have been landed.  Closing bug.