Bug 70634 - Mark GraphicsLayers as opaque when possible
Summary: Mark GraphicsLayers as opaque when possible
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Alok Priyadarshi
URL:
Keywords:
: 40629 (view as bug list)
Depends on: 73040 108354 112454
Blocks: 72412 72980 109507
  Show dependency treegraph
 
Reported: 2011-10-21 12:59 PDT by Dana Jansens
Modified: 2013-04-25 18:07 PDT (History)
29 users (show)

See Also:


Attachments
Patch (5.15 KB, patch)
2011-10-21 13:01 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
Patch (6.55 KB, patch)
2011-10-24 12:41 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
Patch (16.66 KB, patch)
2011-10-25 10:03 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
Patch (16.66 KB, patch)
2011-10-25 10:09 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
Patch (20.81 KB, patch)
2011-10-25 16:22 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
Patch (20.96 KB, patch)
2011-10-25 16:28 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
added rects to opaque functions (21.69 KB, patch)
2011-10-26 13:38 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
moved opaque rect detection into the compositing area computation - saves a RenderLayer tree walk and cleans up the code significantly (26.04 KB, patch)
2011-10-27 10:50 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
addressed feedback, and some discussion. tests will be incoming next. (27.09 KB, patch)
2011-10-27 13:50 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
proposed method for testing contentsOpaque flag via DRT. (12.96 KB, patch)
2011-10-27 16:55 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
consider all RenderObjects in a RenderLayer (55.40 KB, patch)
2011-11-01 11:15 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
consider the union of opaque rects when deciding if a GraphicsLayer is opaque + nits fixes (69.78 KB, patch)
2011-11-04 10:10 PDT, Dana Jansens
no flags Details | Formatted Diff | Diff
move the RenderObject walk (80.13 KB, patch)
2011-11-08 07:51 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
Patch (48.28 KB, patch)
2011-11-14 09:07 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
Patch (47.26 KB, patch)
2011-11-15 15:13 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
Patch (52.85 KB, patch)
2011-11-18 07:47 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
Archive of layout-test-results from ec2-cr-linux-03 (194.18 KB, application/zip)
2011-11-18 08:24 PST, WebKit Review Bot
no flags Details
Column rules are in contents area background. (48.78 KB, patch)
2011-11-21 08:06 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
Remove chromium specific things (46.41 KB, patch)
2011-11-22 10:22 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
Remove tests of directly composited images (44.61 KB, patch)
2011-11-22 11:05 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
Patch (47.94 KB, patch)
2011-11-22 12:13 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
Archive of layout-test-results from ec2-cr-linux-03 (173.40 KB, application/zip)
2011-11-23 02:16 PST, WebKit Review Bot
no flags Details
Patch (38.26 KB, patch)
2011-11-23 12:42 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
Patch (41.98 KB, patch)
2011-11-24 15:18 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
notify backing about content changes in layers (44.06 KB, patch)
2011-11-28 09:07 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
Patch (45.28 KB, patch)
2011-12-05 11:22 PST, Dana Jansens
no flags Details | Formatted Diff | Diff
Archive of layout-test-results from ec2-cr-linux-01 (182.98 KB, application/zip)
2011-12-05 12:01 PST, WebKit Review Bot
no flags Details
Patch (7.28 KB, patch)
2013-01-29 16:28 PST, Alok Priyadarshi
no flags Details | Formatted Diff | Diff
Patch (21.24 KB, patch)
2013-02-05 14:56 PST, Alok Priyadarshi
no flags Details | Formatted Diff | Diff
Patch (21.40 KB, patch)
2013-02-07 13:17 PST, Alok Priyadarshi
no flags Details | Formatted Diff | Diff
updated baselines (153.40 KB, patch)
2013-02-07 23:19 PST, Alok Priyadarshi
webkit.review.bot: commit-queue-
Details | Formatted Diff | Diff
another try to rebaseline (207.64 KB, patch)
2013-02-08 16:22 PST, Alok Priyadarshi
buildbot: commit-queue-
Details | Formatted Diff | Diff
Avoided assert and rebaselined platform/chromium (239.17 KB, patch)
2013-02-08 23:08 PST, Alok Priyadarshi
no flags Details | Formatted Diff | Diff
Updated mac baselines (311.85 KB, patch)
2013-02-20 10:32 PST, Alok Priyadarshi
no flags Details | Formatted Diff | Diff
simplified chainlove.com (402 bytes, text/html)
2013-03-13 22:38 PDT, Alok Priyadarshi
no flags Details
Patch (9.07 KB, patch)
2013-03-14 12:52 PDT, Alok Priyadarshi
no flags Details | Formatted Diff | Diff
Patch (27.58 KB, patch)
2013-03-19 12:18 PDT, Alok Priyadarshi
simon.fraser: review+
webkit.review.bot: commit-queue-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dana Jansens 2011-10-21 12:59:22 PDT
Set the opacity flag for GraphicsLayer.
Comment 1 Dana Jansens 2011-10-21 13:01:21 PDT
Created attachment 112004 [details]
Patch
Comment 2 Dana Jansens 2011-10-21 13:04:33 PDT
I tested this with a z-transformed div and the layer was indeed marked as opaque().

Not sure if this is the right place for the code, but it was the best place I was able to find.  All comments appreciated.

I do wonder how it would interact with
Comment 3 Dana Jansens 2011-10-21 13:05:13 PDT
Sorry, cut off.

I do wonder how it would interact with https://bugs.webkit.org/show_bug.cgi?id=70564
Comment 4 Adrienne Walker 2011-10-21 13:38:41 PDT
Comment on attachment 112004 [details]
Patch

It's possible for multiple layers to go into the same backing, so I think you'll need some sort of bounds check of the layer vs. the bounds of the backing to make sure that a layer with an opaque background color fills the whole space.

I'm not sure how this can be easily tested.  The best I can think of is exposing an isBackingOpaque(RenderObject*) function to windows.internal and then writing a layout test that with a bunch of different cases.

(Also, this is super exciting to see.  You're wanting this for culling, but I also want this sort of information to know whether we can turn on subpixel antialiasing on composited layers.  Although, I guess for that use case the border style checks can be ignored.)
Comment 5 Dana Jansens 2011-10-24 08:40:07 PDT
(In reply to comment #4)
> (From update of attachment 112004 [details])
> It's possible for multiple layers to go into the same backing, so I think you'll need some sort of bounds check of the layer vs. the bounds of the backing to make sure that a layer with an opaque background color fills the whole space.

Why is this needed? The opaque flag is being set for a single /layer/, and I don't understand why that is incorrect when the layer doesn't fill a backing.  Unless you want to add an opaque flag to the backing? Just for testing?
Comment 6 Adrienne Walker 2011-10-24 09:35:35 PDT
(In reply to comment #5)
> (In reply to comment #4)
> > (From update of attachment 112004 [details] [details])
> > It's possible for multiple layers to go into the same backing, so I think you'll need some sort of bounds check of the layer vs. the bounds of the backing to make sure that a layer with an opaque background color fills the whole space.
> 
> Why is this needed? The opaque flag is being set for a single /layer/, and I don't understand why that is incorrect when the layer doesn't fill a backing.  Unless you want to add an opaque flag to the backing? Just for testing?

RenderLayer has an n->1 relationship with RenderLayerBacking.  RenderLayerBacking has a 1-1 relationship with GraphicsLayer.

You're checking the style of a RenderObject for the RenderLayer that was composited and setting a flag on the GraphicsLayer for that RenderLayer's RenderLayerBacking.  Because there's an n->1 relationship along that path, I don't think what you're checking is sufficient.

The owning RenderLayer for the RenderLayerBacking could have RenderLayer descendants that go into the same backing.  Those descendants might not be opaque and might not be contained within the bounding box of the owning RenderLayer.  Maybe take a look at RenderLayerCompositor::calculateCompositedBounds to see what I'm trying to get at.
Comment 7 Dana Jansens 2011-10-24 12:41:38 PDT
Created attachment 112233 [details]
Patch
Comment 8 Dana Jansens 2011-10-24 12:43:56 PDT
Simple logic to make sure no false-positive opaque happens from RenderLayers that don't fill the GraphicsLayer.

There's a FIXME to improve this logic, but the test "do a set of rects fill this rect" is something we can also leverage to decide whether to paint a tile or not (https://bugs.webkit.org/show_bug.cgi?id=70533) so it is a future step to occur in a more general place.

I'll start to look at what some layout tests would look like.
Comment 9 Simon Fraser (smfr) 2011-10-24 13:31:20 PDT
Comment on attachment 112233 [details]
Patch

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

> Source/WebCore/rendering/RenderLayerBacking.cpp:285
> +    if (updateOpaque())
> +        layerConfigChanged = true;

updateGraphicsLayerConfiguration() is about changes to the layer tree structure, not just about setting flags on GraphicsLayers.

> Source/WebCore/rendering/RenderLayerBacking.cpp:614
> +bool RenderLayerBacking::updateOpaqueRenderLayer(RenderLayer* layer, RenderLayer* ancestor, const IntPoint& ancestorDelta)

The method name needs improvement. It's not updating the render layer to be opaque, it's computing whether the layer should be considered opaque.

> Source/WebCore/rendering/RenderLayerBacking.cpp:619
> +    bool seeThru = (style->visitedDependentColor(CSSPropertyBackgroundColor).hasAlpha()

I don't like seeThru.

> Source/WebCore/rendering/RenderLayerBacking.cpp:620
> +                    && (!renderObject->isImage() || !toRenderImage(renderObject)->backgroundIsObscured()))

It would be clearer to separate 'contents are opaque' from 'backgrounds and borders are opaque". It would also make sense to push questions about RenderObject opaqueness down to RenderObject and subclasses. This could share a lot of logic with the code that would be added for bug 49135.

> Source/WebCore/rendering/RenderLayerBacking.cpp:626
> +                   || style->borderLeftIsTransparent()
> +                   || style->borderRightIsTransparent()
> +                   || style->borderTopIsTransparent()
> +                   || style->borderBottomIsTransparent();

You should check to see if there is a border at all.

> Source/WebCore/rendering/RenderLayerBacking.cpp:647
> +    RenderLayer* child = layer->firstChild();
> +    while (child) {
> +        if (updateOpaqueRenderLayer(child, layer, delta))
> +            return true;
> +        child = child->nextSibling();
> +    }

Sucks to do another layer tree walk here (and probably expensive too). If needed, we could compute this same info during one of the existing tree walks.

> Source/WebCore/rendering/RenderLayerBacking.cpp:651
> +bool RenderLayerBacking::updateOpaque()

Needs better name.
Comment 10 Dana Jansens 2011-10-25 10:03:32 PDT
Created attachment 112350 [details]
Patch
Comment 11 Dana Jansens 2011-10-25 10:09:22 PDT
Created attachment 112351 [details]
Patch
Comment 12 Dana Jansens 2011-10-25 10:17:23 PDT
Updated patch to address feedback, except for the extra tree walk.  I hope I understood your critiques correctly, comments below.

(In reply to comment #9)
> (From update of attachment 112233 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=112233&action=review
> updateGraphicsLayerConfiguration() is about changes to the layer tree structure, not just about setting flags on GraphicsLayers.

I believe you meant to not set the layerConfigChanged flag, since the hierarchy didn't change.  If you meant to update the opaque flag in a different location entirely, can you suggest where?

> The method name needs improvement. It's not updating the render layer to be opaque, it's computing whether the layer should be considered opaque.

Renamed to findOpaqueRenderLayer. This will go away once I find another tree walk to merge it into.

> It would be clearer to separate 'contents are opaque' from 'backgrounds and borders are opaque". It would also make sense to push questions about RenderObject opaqueness down to RenderObject and subclasses. This could share a lot of logic with the code that would be added for bug 49135.

From a comment enne@ made, and bug 49135, I split this logic into three pieces:
1. contents foreground (image data etc)
2. contents background (background color)
3. contents exterior (borders, padding, shadow, etc.)

Currently:
- RenderBoxModelObject overrides background and exterior.
- RenderBlock extends exterior for column rule.
- RenderImage overrides foreground.

> You should check to see if there is a border at all.

See RenderBoxModelObject::opaqueContentsExterior, many improvements here.

> Sucks to do another layer tree walk here (and probably expensive too). If needed, we could compute this same info during one of the existing tree walks.

Will work on this piece next, but would appreciate feedback on the rest of the code as it is.

> > Source/WebCore/rendering/RenderLayerBacking.cpp:651
> > +bool RenderLayerBacking::updateOpaque()
> 
> Needs better name.

Renamed to updateContentsOpaque(), since it sets the "contentsOpaque" flag on the graphics layer.  If you're thinking of something else, can you suggest what you're looking for?
Comment 13 Simon Fraser (smfr) 2011-10-25 11:06:22 PDT
Comment on attachment 112351 [details]
Patch

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

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2569
> +static bool opaqueBorder(EBorderStyle bstyle)
> +{
> +    switch (bstyle) {
> +    case BNONE:
> +    case BHIDDEN:
> +    case INSET:
> +    case GROOVE:
> +    case OUTSET:
> +    case RIDGE:
> +    case SOLID:
> +        return true;
> +    case DOTTED:
> +    case DASHED:
> +    case DOUBLE:
> +        return false;
> +    }
> +    ASSERT_NOT_REACHED();
> +}

Seems like this would work as a method on BorderEdge nicely.

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2589
> +    if (style()->hasBorder()
> +        && ((style()->borderLeftWidth() && !opaqueBorder(style()->borderLeftStyle()))
> +         || (style()->borderTopWidth() && !opaqueBorder(style()->borderTopStyle()))
> +         || (style()->borderRightWidth() && !opaqueBorder(style()->borderRightStyle()))
> +         || (style()->borderBottomWidth() && !opaqueBorder(style()->borderBottomStyle())))) {
> +        if (bgClip == BorderFillBox)
> +            bgVisible = true; // Can see the background through the border
> +        else
> +            return false; // Can see through the border, and it isn't filled by the background
> +    }

Would also be better to fit into the BorderEdge logic.

> Source/WebCore/rendering/RenderBoxModelObject.h:123
> +    virtual bool opaqueContentsBackground() const
> +    {
> +        const Color color = style()->visitedDependentColor(CSSPropertyBackgroundColor);
> +        return color.isValid() && !color.hasAlpha();
> +    }

I think you should check for border-radius here.

> Source/WebCore/rendering/RenderObject.h:739
> +    virtual bool opaqueContentsForeground() const { return false; }
> +
> +    // Returns true if the background within the object's contents bounds is known to be completely opaque.
> +    virtual bool opaqueContentsBackground() const { return false; }

We try to use method names that read well; these do not. If you're adding these methods, I'd prefer you pass a rect as required for bug 49135, so they become:

virtual bool foregroundIsOpaqueInRect(const LayoutRect&) const
virtual bool backgroundIsOpaqueInRect(const LayoutRect&) const

> Source/WebCore/rendering/RenderObject.h:743
> +    virtual bool opaqueContentsExterior() const { return false; }

We use 'box decorations' to refer to border, outline, shadow etc. The method name doesn't really say what it does.
Comment 14 Dana Jansens 2011-10-25 16:22:06 PDT
Created attachment 112424 [details]
Patch
Comment 15 WebKit Review Bot 2011-10-25 16:23:57 PDT
Attachment 112424 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WebCore/ChangeLog', u'Source/WebCor..." exit_code: 1

Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:358:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:359:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:360:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:361:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:366:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:367:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:368:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:369:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/ChangeLog:10:  Line contains tab character.  [whitespace/tab] [5]
Total errors found: 9 in 11 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 16 Dana Jansens 2011-10-25 16:28:15 PDT
Created attachment 112427 [details]
Patch
Comment 17 WebKit Review Bot 2011-10-25 16:31:15 PDT
Attachment 112427 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WebCore/ChangeLog', u'Source/WebCor..." exit_code: 1

Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:358:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:359:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:360:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:361:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:366:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:367:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:368:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h:369:  Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.  [readability/comparison_to_zero] [5]
Total errors found: 8 in 11 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 18 Dana Jansens 2011-10-26 13:38:06 PDT
Created attachment 112588 [details]
added rects to opaque functions
Comment 19 Dana Jansens 2011-10-27 10:50:21 PDT
Created attachment 112705 [details]
moved opaque rect detection into the compositing area computation - saves a RenderLayer tree walk and cleans up the code significantly
Comment 20 Dana Jansens 2011-10-27 10:52:40 PDT
I believe I've addressed all review comments up to now in this version, so I'd appreciate another look at the code. Thanks!
Comment 21 Simon Fraser (smfr) 2011-10-27 11:20:06 PDT
Comment on attachment 112705 [details]
moved opaque rect detection into the compositing area computation - saves a RenderLayer tree walk and cleans up the code significantly

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

Getting closer, but I'd like to see the 'isOpaque' code mirror the painting code more closely.

> Source/WebCore/rendering/RenderBlock.cpp:2379
> +inline bool RenderBlock::shouldPaintColumnRules() const

Why doesn't this method check the rule color?

> Source/WebCore/rendering/RenderBlock.cpp:2381
>      bool ruleTransparent = style()->columnRuleIsTransparent();

You could early return here.

> Source/WebCore/rendering/RenderBlock.cpp:2385
>      bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent && ruleWidth <= colGap;

You could eliminate the local variable.

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2562
> +    // If the query rect leaves the render object, then we can't vouch that the entire rect is opaque.
> +    if (!bounds.contains(rect))
> +        return false;

We can if the rect covers an opaque outline or shadow.

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2570
> +    if (!boxDecorationsAreOpaqueInRect(rect))

Why test this here when RenderObject:: isOpaqueInRect() calls both backgroundIsOpaqueInRect() and boxDecorationsAreOpaqueInRect()?

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2594
> +    if (rect.x() >= bounds.x() + borderLeft() + paddingLeft()
> +        && rect.maxX() <= bounds.maxX() - borderRight() - paddingRight()
> +        && rect.y() >= bounds.y() + borderTop() + paddingTop()
> +        && rect.maxY() <= bounds.maxY() - borderBottom() - paddingBottom())

Can't you construct the contentsRect and just use rect methods to test for inclusion?

Also, border-image with 'fill' can cause a box decoration to paint inside the contents box.

I'm confused why this method would return 'true' if the rect is entirely inside the contents box. Perhaps it's confusing to split out box decorations into their own method, because they almost always paint with a hole in the middle. Maybe just merge this and the background-testing code.

In general, the 'is opaque' methods should mirror the painting methods as closely as possible, otherwise it's going to be hard to keep them in sync.

> Source/WebCore/rendering/RenderLayerBacking.cpp:237
> +    // FIXME: Consider the union of all the rects instead of just a single one at a time to prevent many false negatives.
> +    //        In order to do this computation we will need to walk the opaque regions at least once after determining the
> +    //        full compositing bounds, and we will want to sort them to compute this efficiently, so we are collecting them
> +    //        in a vector for that reason.

We don't normally indent comments like this.

> Source/WebCore/rendering/RenderLayerCompositor.cpp:529
> +        axisAligned = affineTrans->isAxisAligned(layer->renderer()->style()->hasPerspective());

This seems like overkill, and isAxisAligned() is nontrivial code. Why not just punt on opaqueness testing if there's any transform?
Comment 22 Simon Fraser (smfr) 2011-10-27 11:20:19 PDT
Also, this needs a bucketload of tests.
Comment 23 Dana Jansens 2011-10-27 13:50:21 PDT
Created attachment 112743 [details]
addressed feedback, and some discussion. tests will be incoming next.
Comment 24 Dana Jansens 2011-10-27 13:51:01 PDT
Comment on attachment 112705 [details]
moved opaque rect detection into the compositing area computation - saves a RenderLayer tree walk and cleans up the code significantly

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

>> Source/WebCore/rendering/RenderBlock.cpp:2379
>> +inline bool RenderBlock::shouldPaintColumnRules() const
> 
> Why doesn't this method check the rule color?

This is testing if the rule is visible at all (i.e. alpha > 0).  It uses style()->columnRuleIsTransparent() to that effect, which checks the color's alpha value in BorderValue::isTransparent().

>> Source/WebCore/rendering/RenderBlock.cpp:2381
>>      bool ruleTransparent = style()->columnRuleIsTransparent();
> 
> You could early return here.

I turned the function into a set of "if (fail) { return }" to early return for each test.

>> Source/WebCore/rendering/RenderBlock.cpp:2385
>>      bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent && ruleWidth <= colGap;
> 
> You could eliminate the local variable.

Done, all local variables removed even.

>> Source/WebCore/rendering/RenderBoxModelObject.cpp:2562
>> +        return false;
> 
> We can if the rect covers an opaque outline or shadow.

You're right, the comment says more than it should.  I moved the comment directly below up here instead, which says basically: Outside the border bounds is hard and we're not doing that right now.  I can add a FIXME if you would like, but I think it's something to be done in a future CL if it really is a common use case.

Also changed similar comment in boxDecorationsAreOpaque().

>> Source/WebCore/rendering/RenderBoxModelObject.cpp:2570
>> +    if (!boxDecorationsAreOpaqueInRect(rect))
> 
> Why test this here when RenderObject:: isOpaqueInRect() calls both backgroundIsOpaqueInRect() and boxDecorationsAreOpaqueInRect()?

My thought was to make backgroundIsOpaqueInRect() function on its own, but it is called twice now.

I have removed the call here, and added a comment to the effect on backgroundIsOpaqueInRect(), similar to the foreground version.

isOpaqueInRect() becomes true if (box decor && (foreground || background)).

>> Source/WebCore/rendering/RenderBoxModelObject.cpp:2594
>> +        && rect.maxY() <= bounds.maxY() - borderBottom() - paddingBottom())
> 
> Can't you construct the contentsRect and just use rect methods to test for inclusion?
> 
> Also, border-image with 'fill' can cause a box decoration to paint inside the contents box.
> 
> I'm confused why this method would return 'true' if the rect is entirely inside the contents box. Perhaps it's confusing to split out box decorations into their own method, because they almost always paint with a hole in the middle. Maybe just merge this and the background-testing code.
> 
> In general, the 'is opaque' methods should mirror the painting methods as closely as possible, otherwise it's going to be hard to keep them in sync.

Fixed to use a rect.

Border-image seems complex, and ignoring it completely will possibly make for false negatives, but not positives, so I'd like to just leave it out for this CL.  Have put in a comment here and in backgroundIsOpaqueInRect() to mention its existence.

Consider if the background color is not opaque, however the borders are opaque, there is no padding, and the foreground contents area is opaque.  Then the render object is opaque.

For this reason, I split the code into these three functions, so that (foreground && box decor) || (background && box decor) would be possible.  Otherwise the foreground check's usefulness is degraded (You'd need 4+ queries on the background pieces around it as well). I will make this more clear in the comment here and on the function in RenderObject.h.  Am I understanding this correctly?

>> Source/WebCore/rendering/RenderLayerBacking.cpp:237
>> +    //        in a vector for that reason.
> 
> We don't normally indent comments like this.

Done.

>> Source/WebCore/rendering/RenderLayerCompositor.cpp:529
>> +        axisAligned = affineTrans->isAxisAligned(layer->renderer()->style()->hasPerspective());
> 
> This seems like overkill, and isAxisAligned() is nontrivial code. Why not just punt on opaqueness testing if there's any transform?

Right angle rotations are an important use case here.  For example, with screen rotations, and losing opaqueness optimizations because of drawing on a 90 degree turn is a big loss.  While it looks complex at a glance, the code is checking 1 bool, and at most 12 ints for non-zero state.  isIdentityOrTransform() is checking 13.  I could write isAxisAligned() in a different manner if that would help, with more if statements and early returns.
Comment 25 Dana Jansens 2011-10-27 16:54:13 PDT
Regarding testing:

I think the right way to test this is to add contentsOpaque to the output of GraphicsLayer::dumpProperties().  However this change alone which break and require rebaselining a *lot* of layout tests.

There are many ways this could go and I'd like to know what you all think is the best.

First I'll say my own thoughts:  Currently LayoutTestController.layoutTreeAsText(bool) takes an argument to show debug info.  If we extend this to allow setting various flags for layoutTreeAsText(), we can enable "contentsOpaque" in the DRT output only when we want it, and expose this to tests.

To do this:
- Remove boolean argument to layoutTreeAsText().
- Add setLayerTreeAsTextFlag(string, bool) to LayoutTestController.
  - Eventually this string is parsed to a value from the enum LayerTreeAsTextBehaviourFlags in GraphicsLayer.h

The big win here is that we can use DRT output to test this property nicely, without having to rebaseline any other tests.  If/when future properties are flipped on in GraphicsLayer or equivalent, this could pay off there also.

I will attach a patch to give an idea what this would look like.
Comment 26 Dana Jansens 2011-10-27 16:55:31 PDT
Created attachment 112783 [details]
proposed method for testing contentsOpaque flag via DRT.
Comment 27 Simon Fraser (smfr) 2011-10-27 16:58:25 PDT
(In reply to comment #25)
> Regarding testing:
> 
> I think the right way to test this is to add contentsOpaque to the output of GraphicsLayer::dumpProperties().  However this change alone which break and require rebaselining a *lot* of layout tests.

No, not if you only print it out when it has the non-default value.

> First I'll say my own thoughts:  Currently LayoutTestController.layoutTreeAsText(bool) takes an argument to show debug info.  If we extend this to allow setting various flags for layoutTreeAsText(), we can enable "contentsOpaque" in the DRT output only when we want it, and expose this to tests.
> 
> To do this:
> - Remove boolean argument to layoutTreeAsText().
> - Add setLayerTreeAsTextFlag(string, bool) to LayoutTestController.
>   - Eventually this string is parsed to a value from the enum LayerTreeAsTextBehaviourFlags in GraphicsLayer.h
> 
> The big win here is that we can use DRT output to test this property nicely, without having to rebaseline any other tests.  If/when future properties are flipped on in GraphicsLayer or equivalent, this could pay off there also.
> 
> I will attach a patch to give an idea what this would look like.

No need for any of this. Just print out contentsOpaque when it's true.
Comment 28 Dana Jansens 2011-10-27 17:04:42 PDT
(In reply to comment #27)
> (In reply to comment #25)
> > Regarding testing:
> > 
> > I think the right way to test this is to add contentsOpaque to the output of GraphicsLayer::dumpProperties().  However this change alone which break and require rebaselining a *lot* of layout tests.
> 
> No, not if you only print it out when it has the non-default value.
...
> 
> No need for any of this. Just print out contentsOpaque when it's true.

The default value is non-opaque, since we want to assume things blend if we're not sure. But I imagine most tests actually actually use opaque layers, and the root layer should always be opaque. How come this won't make all these tests fail?
Comment 29 Simon Fraser (smfr) 2011-10-27 17:17:55 PDT
(In reply to comment #28)
> (In reply to comment #27)
> > (In reply to comment #25)
> > > Regarding testing:
> > > 
> > > I think the right way to test this is to add contentsOpaque to the output of GraphicsLayer::dumpProperties().  However this change alone which break and require rebaselining a *lot* of layout tests.
> > 
> > No, not if you only print it out when it has the non-default value.
> ...
> > 
> > No need for any of this. Just print out contentsOpaque when it's true.
> 
> The default value is non-opaque, since we want to assume things blend if we're not sure. But I imagine most tests actually actually use opaque layers, and the root layer should always be opaque. How come this won't make all these tests fail?

I think we omit the root layer from the layer dump to avoid platform differences. You're right in that some existing tests may have opaque layers, but that's a progression we'd like to know about. You'll just have to land new results.
Comment 30 Simon Fraser (smfr) 2011-10-27 17:21:57 PDT
Comment on attachment 112783 [details]
proposed method for testing contentsOpaque flag via DRT.

Just print out m_contentsOpaque if it has the non-default value.
Comment 31 Adrienne Walker 2011-10-27 17:30:09 PDT
(In reply to comment #25)
> Regarding testing:
> 
> I think the right way to test this is to add contentsOpaque to the output of GraphicsLayer::dumpProperties().  However this change alone which break and require rebaselining a *lot* of layout tests.

Maybe everybody disagrees with my position on this, but I personally don't think this is the right way to go.  One of the big problems with layout tests in my opinion is that they over-test.  Over-testing leads to needless rebaselining and fragile tests, which makes the signal that they provide ultimately less useful.

In some theoretical world, the ideal approach for this bug would be to write a few tests that specifically test the opacity flag.  Modifying the testing structure so that every test starts testing the opacity flag in addition to what it's already testing seems like a backwards design.

Adding a function to specifically test opacity in window.internals is what I suggested earlier.  Adding a filter to layoutTreeAsText could also be an approach that could limit the impact to other tests.
Comment 32 Dana Jansens 2011-11-01 11:15:22 PDT
Created attachment 113198 [details]
consider all RenderObjects in a RenderLayer
Comment 33 Dana Jansens 2011-11-01 11:17:19 PDT
There are a few LayoutTests included now, which showed some bugs/omissions in the previous code.  Wanted to verify that this is still heading in the right direction.  The code now traverses the RenderObjects associated with a RenderLayer to find all the opaque regions, instead of just 1 per RenderLayer.

More tests will be coming, but this is a start.
Comment 34 Simon Fraser (smfr) 2011-11-01 12:08:48 PDT
Comment on attachment 113198 [details]
consider all RenderObjects in a RenderLayer

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

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2678
> +    // We do not consider overflow bounds here, and if we get a query rect on the overflow area for the
> +    // render object (i.e. outside the border bounds), then we just return false. This does not mean the area
> +    // in the rect is neccessarily non-opaque, and may be a false negative.
> +    // NOTE: Because of this, we don't need to look for style()->boxShadow(), since that is always outside of the border
> +    // bounds.
> +    if (!bounds.contains(rect))
> +        return false;
> +
> +    // FIXME: Check border-image. With 'fill' it can be drawn behind the contents area and could be opaque.
> +
> +    const Color color = style()->visitedDependentColor(CSSPropertyBackgroundColor);
> +    if (!color.isValid() || color.hasAlpha())
> +        return false;

I think these new methods need to be written conservatively; they should err towards returning 'false' unless known to be opaque. Then the FIXME becomes harmless.

> Source/WebCore/rendering/RenderLayerBacking.cpp:244
> +    bool opaque = false;
> +    for (size_t i = 0; i < opaqueRegions.size(); ++i)
> +        if (opaqueRegions[i].contains(layerBounds)) {
> +            opaque = true;
> +            break;
> +        }
> +    m_graphicsLayer->setContentsOpaque(opaque);

Rather than collect rects like this, why not just have calculateCompositedBounds() have an out param that returns whether the layers are known to be fully opaque in the given bounds? Then you could avoid extra work as soon as you find out that it is not.

> Source/WebCore/rendering/RenderLayerCompositor.cpp:452
> +void recursiveCollectOpaqueRenderObjects(const RenderLayer* layer, const RenderObject* renderer, const RenderBoxModelObject* container, Vector<LayoutRect>& opaqueRegions, LayoutPoint totalRelOffset)

We prefer static methods to using anonymous namespaces.

> Source/WebCore/rendering/RenderLayerCompositor.cpp:455
> +        const RenderBoxModelObject* boxmodel = static_cast<const RenderBoxModelObject*>(renderer);

Don't like boxmodel as a variable name. It's a boxModelObject.

> Source/WebCore/rendering/RenderLayerCompositor.cpp:458
> +        if (boxmodel->layer() && boxmodel->layer() != layer)
> +            return; // We've left the render layer.

This is wrong. RenderBoxModelObject::layer() only returns a RL if the RO has one; it never returns the layer for some ancestor RO.

> Source/WebCore/rendering/RenderLayerCompositor.cpp:468
> +        if (boxmodel->isOpaqueInRect(area)) {
> +            area.move(containerOffset);
> +            opaqueRegions.append(area);
> +        }

The approach taken here is doing an exhaustive walk of all the RO even when one is found to be non-opaque. This could get very expensive. You need to be able to bail early if you find non-opaque content. Ideally we'd do this testing at the same time as some other tree-walk (maybe you cache it during painting).

> Source/WebCore/rendering/RenderLayerCompositor.cpp:472
> +        // Containers are not always parents, so in general it is not okay to just assume we are the container for our
> +        // child because we are its parent. However, if we are not its container (for e.g. it is positioned absolute and has
> +        // a different container), then it will also be composited independently, and have its own RenderLayer/GraphicsLayer.

The comment (and maybe the code) is confused. Not every RL has a GL. A GL can render a subtree of RLs.

> Source/WebCore/rendering/RenderObject.h:749
> +    // Returns true if the foreground within the query rect will be filled completely opaque by the RenderObject.
> +    // This checks only within the contents area of the RenderObject, so if you want to test the entire surface
> +    // area, you need to test boxDecorationsAreOpaqueInRect() as well.
> +    virtual bool foregroundIsOpaqueInRect(const IntRect&) const { return false; }
> +
> +    // Returns true if the background within the query rect will be filled completely opaque by the RenderObject.
> +    // This checks only within the contents area of the RenderObject, so if you want to test the entire surface
> +    // area, you need to test boxDecorationsAreOpaqueInRect() as well.
> +    virtual bool backgroundIsOpaqueInRect(const IntRect&) const { return false; }
> +
> +    // Returns true if the background within the query rect would be filled completely opaque (assuming the content area was opaque).
> +    // This returns true if the query rect is entirely in the contents area of the render object, as the opaque result depends
> +    // only on the foregroundIsOpaqueInRect() or backgroundIsOpaqueInRect() result. A true result from this function should
> +    // *never* be used without also consulting at least one of the previously mentioned functions as well.
> +    virtual bool boxDecorationsAreOpaqueInRect(const IntRect&) const { return false; }

The verbosity of the comments indicates that there's something wrong with the code factoring and/or the method names.

> LayoutTests/compositing/opaque/borders.html:67
> +      layoutTestController.waitUntilDone();
> +    }
> +
> +    function doTest()
> +    {
> +      if (window.layoutTestController) {
> +        document.getElementById('layers').innerText = layoutTestController.layerTreeAsText();
> +        layoutTestController.notifyDone();
> +      }
> +    }
> +    
> +    window.addEventListener('load', doTest, false);

You don't need waitUntilDone if your test finishes inside the load event.
Comment 35 Dana Jansens 2011-11-01 13:51:54 PDT
Comment on attachment 113198 [details]
consider all RenderObjects in a RenderLayer

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

Thanks for the comments. The process for determining if a GraphicsLayer is opaque is still very simplified in this patch (Does some RenderObject fully occlude the GraphicsLayer?) but this is far from sufficient.  The goal is to determine if the union of opaque ROs fully occlude the GL. More comments inline.

>> Source/WebCore/rendering/RenderBoxModelObject.cpp:2678
>> +        return false;
> 
> I think these new methods need to be written conservatively; they should err towards returning 'false' unless known to be opaque. Then the FIXME becomes harmless.

I do agree, and I thought that was what I had done.  Currently this function returns true only if the query rect is entirely over the background color, and the background color is opaque.

It would be possible to do this with early exit returning true instead (though I think there would have to be only a single early exit then, since it is basically an AND of all the conditions to get to the true statement.

if (contains && colorvalid && !colorhasalpha)
    return true;
return false;

Would that be preferable to you?  Or I could include a comment indicating this intent also.

>> Source/WebCore/rendering/RenderLayerBacking.cpp:244
>> +    m_graphicsLayer->setContentsOpaque(opaque);
> 
> Rather than collect rects like this, why not just have calculateCompositedBounds() have an out param that returns whether the layers are known to be fully opaque in the given bounds? Then you could avoid extra work as soon as you find out that it is not.

The reason we collect rects here rather than computing as soon as we find a new rect, is that in order to determine if the union of the rects cover the GraphicsLayer in some reasonable (polynomial) amount of time, we will need to do something like sorting the rects.  For this reason I collect them into a Vector which can be easily sorted and then tested for covering.

It doesn't look needed right now, since the test is simply checking for a single RO that covers the GraphicsLayer, but that's not the final intent, as that misses a lot (A composited div with two divs in it, etc).

>> Source/WebCore/rendering/RenderLayerCompositor.cpp:452
>> +void recursiveCollectOpaqueRenderObjects(const RenderLayer* layer, const RenderObject* renderer, const RenderBoxModelObject* container, Vector<LayoutRect>& opaqueRegions, LayoutPoint totalRelOffset)
> 
> We prefer static methods to using anonymous namespaces.

Fixing.

>> Source/WebCore/rendering/RenderLayerCompositor.cpp:455
>> +        const RenderBoxModelObject* boxmodel = static_cast<const RenderBoxModelObject*>(renderer);
> 
> Don't like boxmodel as a variable name. It's a boxModelObject.

Fixing.

>> Source/WebCore/rendering/RenderLayerCompositor.cpp:458
>> +            return; // We've left the render layer.
> 
> This is wrong. RenderBoxModelObject::layer() only returns a RL if the RO has one; it never returns the layer for some ancestor RO.

Can it return a decendant's RenderLayer?  The intent here was to prevent looking at any RO that are inside another RL (since we are walking the RLs already in calculateCompositedBounds.  If RL->renderer() points to a subtree of RO that all belong to the single RL, then we can remove this check. Otherwise what should we do instead to  not look at a RO twice.

>> Source/WebCore/rendering/RenderLayerCompositor.cpp:468
>> +        }
> 
> The approach taken here is doing an exhaustive walk of all the RO even when one is found to be non-opaque. This could get very expensive. You need to be able to bail early if you find non-opaque content. Ideally we'd do this testing at the same time as some other tree-walk (maybe you cache it during painting).

Yes, because the intent is to determine if the union of opaque ROs cover the entire GraphicsLayer. To do so, we need to find them all since they can be in arbitrary positions within the GraphicsLayer, unless there is some underlying structure here that I can take advantage of and am not right now?  As I understood, a non-opaque RO could still be above/below some (set of) opaque RO belonging to the current or other RenderLayers in the GraphicsLayer.

>> Source/WebCore/rendering/RenderLayerCompositor.cpp:472
>> +        // a different container), then it will also be composited independently, and have its own RenderLayer/GraphicsLayer.
> 
> The comment (and maybe the code) is confused. Not every RL has a GL. A GL can render a subtree of RLs.

The comment meant to say that such a RO will be composited and thus be in a different GraphicsLayer, which implies a different RenderLayer. I will fix that.

>> Source/WebCore/rendering/RenderObject.h:749
>> +    virtual bool boxDecorationsAreOpaqueInRect(const IntRect&) const { return false; }
> 
> The verbosity of the comments indicates that there's something wrong with the code factoring and/or the method names.

Will improve for clarity by refering to the content rect in the names, and shorten the comments.

foregroundContentsAreOpaqueInRect()
backgroundContentsAreIsOpaqueInRect()

>> LayoutTests/compositing/opaque/borders.html:67
>> +    window.addEventListener('load', doTest, false);
> 
> You don't need waitUntilDone if your test finishes inside the load event.

Thanks.
Comment 36 Dana Jansens 2011-11-04 10:10:30 PDT
Created attachment 113673 [details]
consider the union of opaque rects when deciding if a GraphicsLayer is opaque + nits fixes
Comment 37 Dana Jansens 2011-11-04 10:14:44 PDT
The last patch addresses the smaller things you've brought up, hopefully sufficiently, as well as considers the full union of opaque rects when deciding if the opaque flag should be set or not.

Using the painting tree walk would be problematic, I believe, since properties change between paints, and we would like to know the opaque state during the painting process to limit painting as well as blitting to the screen.

However, the layout tree walk was suggested as a place for this computation.  I will look into using the RenderObject walk there.
Comment 38 Dana Jansens 2011-11-08 07:51:23 PST
Created attachment 114066 [details]
move the RenderObject walk
Comment 39 Dana Jansens 2011-11-08 08:01:16 PST
This version moves the walk of RenderObjects to the RenderObject::layout() code paths.

I'm not sure if this will be an overall win when compared to the previous version, but will leave it to you to judge. This buys us more lines of code (37 more), and spreads the opaque computation out to 3 classes:
- RenderLayerCompositor walks RenderLayers, collects their opaque regions, and determines if they cover the entire backing.
- RenderLayer holds a set of opaque regions given to it by RenderObjects.
- RenderObject computes an opaque region for itself after layout() and gives it to its enclosingLayer().

When a RenderObject saves its opaque rectangle, it needs to save an offset relative to its enclosing RenderLayer.  The old code did this by keeping an aggregate offset and thus required no extra computation to determine the offset. We don't have the same information here in this version, so after a RenderObject completes its layout(), we have to walk up to the enclosing RenderLayer to determine its offset (also to determine its enclosing RenderLayer).

I see code that walks up to container() used a fair bit in the layout code, so the above walk up to enclosingLayer() may not be a big deal in this part of the code (compared to RenderLayerCompositor::calculateCompositedBounds(), but I wanted to point it out.

It would be possible to pass data along to subsequent layout() calls when recursing down the tree, saving some walking (only walk to nearest container() not to enclosingLayer()), but I did not do that since the layout() function is sprinkled around something like 15 classes in the RenderObject hierarchy and it seemed a poor idea to make that sort of change.
Comment 40 Early Warning System Bot 2011-11-08 08:25:21 PST
Comment on attachment 114066 [details]
move the RenderObject walk

Attachment 114066 [details] did not pass qt-ews (qt):
Output: http://queues.webkit.org/results/10380037
Comment 41 Gyuyoung Kim 2011-11-08 08:57:00 PST
Comment on attachment 114066 [details]
move the RenderObject walk

Attachment 114066 [details] did not pass efl-ews (efl):
Output: http://queues.webkit.org/results/10365106
Comment 42 WebKit Review Bot 2011-11-08 18:14:43 PST
Comment on attachment 114066 [details]
move the RenderObject walk

Attachment 114066 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/10376247

New failing tests:
fast/events/scale-and-scroll-iframe-window.html
platform/gtk/scrollbars/overflow-scrollbar-horizontal-wheel-scroll.html
scrollbars/disabled-scrollbar.html
scrollbars/scrollbar-buttons.html
media/media-blocked-by-willsendrequest.html
scrollbars/listbox-scrollbar-combinations.html
fast/events/scale-and-scroll-window.html
scrollbars/hidden-iframe-scrollbar-crash2.html
fast/frames/iframe-double-scale-contents.html
scrollbars/overflow-custom-scrollbar-crash.html
scrollbars/hidden-iframe-scrollbar-crash.html
fast/events/scale-and-scroll-body.html
fast/events/scale-and-scroll-iframe-body.html
scrollbars/basic-scrollbar.html
scrollbars/overflow-scrollbar-combinations.html
Comment 43 Simon Fraser (smfr) 2011-11-09 11:22:24 PST
Comment on attachment 114066 [details]
move the RenderObject walk

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

I don't like that this patch is getting more and more complex. I think you should start by getting the easy cases working first (e.g. the layer's RenderObject is known to be opaque), and then progress to doing RenderObject walks in later patches. The IntRectEdge code is a large amount of new code. It should be tested on all platforms, not just Chromium, but I'd prefer that it just not be included in the initial patch.

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2693
> +    const LayoutRect& bounds = borderBoundingBox();
> +
> +    // We do not consider overflow bounds here, and if we get a query rect on the overflow area for the
> +    // render object (i.e. outside the border bounds), then we just return false. This does not mean the area
> +    // in the rect is neccessarily non-opaque, and may be a false negative.
> +    // NOTE: Because of this, we don't need to look for style()->boxShadow(), since that is always outside of the border
> +    // bounds.
> +    if (!bounds.contains(rect))
> +        return false;
> +
> +    // FIXME: Check border-image. With 'fill' it can be drawn behind the contents area and could be opaque.
> +    // Currently we check background color only, but border-image could make the rect opaque even though the
> +    // background color is not.
> +
> +    const Color color = style()->visitedDependentColor(CSSPropertyBackgroundColor);
> +    if (!color.isValid() || color.hasAlpha())
> +        return false;
> +
> +    return true;

This is contrary to the direction I expressed a preference for. I think the methods should default to returning false, and return true only in cases they know they can give the correct answer for.

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2740
> +    return true;

Ditto.

> Source/WebCore/rendering/RenderImage.cpp:432
> +    return true;

Ditto.

> Source/WebCore/rendering/RenderLayer.h:794
> +    // This is a mapping from RenderObject* to IntRect, which is the opaque rect for each RenderObject
> +    // belonging to this RenderLayer.
> +    HashMap<const RenderObject*, IntRect> m_opaqueRectForRenderObject;
> +
> +    // This list contains bounding box rectangles of opaque RenderObjects in the layer.
> +    OwnPtr<Vector<IntRectEdge> > m_opaqueRectsList;

It seems wrong to be adding these members to RenderLayer, when there's no contract about who updates them. A caller has no way to know if opaqueRects() will be return a stale list. There's just an implicit contract that RenderLayerBacking will update the rects at the right time.

> Source/WebCore/rendering/RenderLayerCompositor.cpp:474
> +    LayoutPoint ancestorRelOffset;
> +    layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset);

Have you tested composited layers that contain 2d-transformed layers? It seems like this convertToLayerCoords() could cross a transform boundary, which is bad.

> Source/WebCore/rendering/RenderObject.cpp:2703
> +void RenderObject::updateOpaqueRect()

I don't know why this has to be on RenderObject, since it's a layer thing.

> Source/WebCore/rendering/RenderObject.h:1004
> +        updateOpaqueRect();

This is going to be way too expensive. This is a hot function (hence the inline).
Comment 44 Dana Jansens 2011-11-09 17:01:27 PST
(In reply to comment #43)
> (From update of attachment 114066 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=114066&action=review
> 
> I don't like that this patch is getting more and more complex. I think you should start by getting the easy cases working first (e.g. the layer's RenderObject is known to be opaque), and then progress to doing RenderObject walks in later patches. The IntRectEdge code is a large amount of new code. It should be tested on all platforms, not just Chromium, but I'd prefer that it just not be included in the initial patch.

I was starting to feel the same way, and I'll be happy to do so. I feel I should clarify what the patch will lose though in the process.

The IntRectEdge code was used to determine if the RenderLayers in a backing together would make it opaque.  Removing that will revert the check to this back to "is there a single opaque RenderLayer that fills the backing?"

I think the inconsistency I wanted to pointed here is that the IntRectEdge code has less to do with walking the RenderObject tree, and more to do with considering all the layers in a backing together (eventually all the RenderObjects in a backing).

Regarding testing: The IntRectEdge code will be tested by LayoutTests across all platforms. But I wanted a unit test also for the unionOfRectsCoverARect logic, especially while I was writing it. I would write unit tests for all platforms if such a general mechanism existed, but to my knowledge it does not?

> 
> > Source/WebCore/rendering/RenderBoxModelObject.cpp:2693
> > +    const LayoutRect& bounds = borderBoundingBox();
> > +
> > +    // We do not consider overflow bounds here, and if we get a query rect on the overflow area for the
> > +    // render object (i.e. outside the border bounds), then we just return false. This does not mean the area
> > +    // in the rect is neccessarily non-opaque, and may be a false negative.
> > +    // NOTE: Because of this, we don't need to look for style()->boxShadow(), since that is always outside of the border
> > +    // bounds.
> > +    if (!bounds.contains(rect))
> > +        return false;
> > +
> > +    // FIXME: Check border-image. With 'fill' it can be drawn behind the contents area and could be opaque.
> > +    // Currently we check background color only, but border-image could make the rect opaque even though the
> > +    // background color is not.
> > +
> > +    const Color color = style()->visitedDependentColor(CSSPropertyBackgroundColor);
> > +    if (!color.isValid() || color.hasAlpha())
> > +        return false;
> > +
> > +    return true;
> 
> This is contrary to the direction I expressed a preference for. I think the methods should default to returning false, and return true only in cases they know they can give the correct answer for.

Understood, I will change how these are written.

> > Source/WebCore/rendering/RenderBoxModelObject.cpp:2740
> > +    return true;
> 
> Ditto.
> 
> > Source/WebCore/rendering/RenderImage.cpp:432
> > +    return true;
> 
> Ditto.
> 
> > Source/WebCore/rendering/RenderLayer.h:794
> > +    // This is a mapping from RenderObject* to IntRect, which is the opaque rect for each RenderObject
> > +    // belonging to this RenderLayer.
> > +    HashMap<const RenderObject*, IntRect> m_opaqueRectForRenderObject;
> > +
> > +    // This list contains bounding box rectangles of opaque RenderObjects in the layer.
> > +    OwnPtr<Vector<IntRectEdge> > m_opaqueRectsList;
> 
> It seems wrong to be adding these members to RenderLayer, when there's no contract about who updates them. A caller has no way to know if opaqueRects() will be return a stale list. There's just an implicit contract that RenderLayerBacking will update the rects at the right time.

- The set of opaque rects is contained in the RenderLayer, since we already walk RenderLayers for any given backing, and it is easier to tell which Layer a RO belongs to, than which backing.
- The /set/ of opaque rects in a RenderLayer is updated by each RenderObject. When the RenderObject makes a change to its opaque rect, the list is marked dirty (by being deleted).
- The list of opaque rects is rebuilt by RenderLayer whenever the list is requested, and the previous list was dirtied. Thus, the backing does not actually update the list explicitly, it just queries on the RenderLayer, who builds the list if required and returns it. And a dirty list is never returned.

I don't particularly like this approach though, either. Is there another RO tree walk that could be considered? The previous patch was a lot cleaner.

> > Source/WebCore/rendering/RenderLayerCompositor.cpp:474
> > +    LayoutPoint ancestorRelOffset;
> > +    layer->convertToLayerCoords(ancestorLayer, ancestorRelOffset);
> 
> Have you tested composited layers that contain 2d-transformed layers? It seems like this convertToLayerCoords() could cross a transform boundary, which is bad.

Will look at this, thank you.

> > Source/WebCore/rendering/RenderObject.cpp:2703
> > +void RenderObject::updateOpaqueRect()
> 
> I don't know why this has to be on RenderObject, since it's a layer thing.

Each RO has an opaque Rect (its entire area or an empty rect at the moment).  This function mostly was added to not interact with the RenderLayer class in the .h file as that would need another include.  It's purpose is to determine if "this" is opaque and update its opaque rect in the RenderLayer's set.

> > Source/WebCore/rendering/RenderObject.h:1004
> > +        updateOpaqueRect();
> 
> This is going to be way too expensive. This is a hot function (hence the inline).

I had the impression that the function is especially hot when b==true (marking as needing layout). Is that incorrect? With b==false, the function is called once per layout(). And if the updating is to be done in the layout() tree walk, then it needs to be done exactly this many times.

As above, is there a better tree walk to consider than layout()?


I will split this bug into two, so we can do the next step and discuss it in a new bug. I'll copy this comment over as well, as I have questions not related to the simpler version. Thanks.
Comment 45 Simon Fraser (smfr) 2011-11-09 17:14:00 PST
(In reply to comment #44)
> (In reply to comment #43)
> > (From update of attachment 114066 [details] [details])
> > View in context: https://bugs.webkit.org/attachment.cgi?id=114066&action=review
> > 
> > I don't like that this patch is getting more and more complex. I think you should start by getting the easy cases working first (e.g. the layer's RenderObject is known to be opaque), and then progress to doing RenderObject walks in later patches. The IntRectEdge code is a large amount of new code. It should be tested on all platforms, not just Chromium, but I'd prefer that it just not be included in the initial patch.
> 
> I was starting to feel the same way, and I'll be happy to do so. I feel I should clarify what the patch will lose though in the process.
> 
> The IntRectEdge code was used to determine if the RenderLayers in a backing together would make it opaque.  Removing that will revert the check to this back to "is there a single opaque RenderLayer that fills the backing?"
> 
> I think the inconsistency I wanted to pointed here is that the IntRectEdge code has less to do with walking the RenderObject tree, and more to do with considering all the layers in a backing together (eventually all the RenderObjects in a backing).
> 
> Regarding testing: The IntRectEdge code will be tested by LayoutTests across all platforms. But I wanted a unit test also for the unionOfRectsCoverARect logic, especially while I was writing it. I would write unit tests for all platforms if such a general mechanism existed, but to my knowledge it does not?

Can you use platform/graphics/Region.h instead for this?

> > > Source/WebCore/rendering/RenderLayer.h:794
> > > +    // This is a mapping from RenderObject* to IntRect, which is the opaque rect for each RenderObject
> > > +    // belonging to this RenderLayer.
> > > +    HashMap<const RenderObject*, IntRect> m_opaqueRectForRenderObject;
> > > +
> > > +    // This list contains bounding box rectangles of opaque RenderObjects in the layer.
> > > +    OwnPtr<Vector<IntRectEdge> > m_opaqueRectsList;
> > 
> > It seems wrong to be adding these members to RenderLayer, when there's no contract about who updates them. A caller has no way to know if opaqueRects() will be return a stale list. There's just an implicit contract that RenderLayerBacking will update the rects at the right time.
> 
> - The set of opaque rects is contained in the RenderLayer, since we already walk RenderLayers for any given backing, and it is easier to tell which Layer a RO belongs to, than which backing.
> - The /set/ of opaque rects in a RenderLayer is updated by each RenderObject. When the RenderObject makes a change to its opaque rect, the list is marked dirty (by being deleted).
> - The list of opaque rects is rebuilt by RenderLayer whenever the list is requested, and the previous list was dirtied. Thus, the backing does not actually update the list explicitly, it just queries on the RenderLayer, who builds the list if required and returns it. And a dirty list is never returned.
> 
> I don't particularly like this approach though, either. Is there another RO tree walk that could be considered? The previous patch was a lot cleaner.

Let's do this in the other bug.
> I will split this bug into two, so we can do the next step and discuss it in a new bug. I'll copy this comment over as well, as I have questions not related to the simpler version. Thanks.

Sounds good.
Comment 46 Dana Jansens 2011-11-14 09:07:54 PST
Created attachment 114960 [details]
Patch
Comment 47 Dana Jansens 2011-11-14 09:13:25 PST
(In reply to comment #45)
> Can you use platform/graphics/Region.h instead for this?

Yes, that looks like a very appropriate place for such things.


So here is the simpler version of the patch.  Considers a single RenderObject per RenderLayer in a backing.  The backing is considered opaque iff any single such RenderObject fills the entire backing and is opaque.

The *AreOpaqueInRect() functions are rewritten as requested.
Comment 48 Simon Fraser (smfr) 2011-11-15 12:12:34 PST
Comment on attachment 114960 [details]
Patch

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

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2673
> +bool RenderBoxModelObject::backgroundContentsAreOpaqueInRect(const IntRect& rect) const

'contents' in the name makes me wonder if this method checks the contentBox only, which it does not. I think backgroundIsOpaqueInRect is better.

Why not check for alpha in background images?

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2682
> +    const bool fullyContainQueryRect = bounds.contains(rect);

Why not early 'return false' here?

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2689
> +    const Color bgColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
> +    const bool bgColorIsOpaque = bgColor.isValid() && !bgColor.hasAlpha();

We don't normally use const on local variables.

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2694
> +bool RenderBoxModelObject::boxDecorationsAreOpaqueInRect(const IntRect& rect) const

I think a better blame would be boxDecorationAreaIsOpaqueInRect().

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2699
> +    // If the query rect leaves the render object, then we can't vouch that the entire rect is opaque.
> +    const bool fullyContainQueryRect = bounds.contains(rect);

You should early return here to avoid all the extra work later in the method.

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2711
> +    const LayoutRect contentsBounds(bounds.x() + borderLeft() + paddingLeft(),
> +                                    bounds.y() + borderTop() + paddingTop(),
> +                                    bounds.width() - borderLeft() - borderRight() - paddingLeft() - paddingRight(),
> +                                    bounds.height() - borderTop() - borderBottom() - paddingTop() - paddingBottom());

I'm surprised we don't have method that does this already.

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2712
> +    const bool contentsFullyContainQueryRect = contentsBounds.contains(rect);

Another opportunity for an early return?

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2736
> +        // If the above for loop completed, then all borders obscure the background.
> +        if (i > BSLeft)
> +            bordersOpaque = true;

It would be clearer just to set a flag from within the loop (then you can make i a variable with loop scope).

A future optimization could only look at the borders that intersect 'rect', also. Add a FIXME comment?

> Source/WebCore/rendering/RenderBoxModelObject.cpp:2745
> +
> +

Two blank lines.

> Source/WebCore/rendering/RenderImage.cpp:418
> +    const bool fullyContainQueryRect = bounds.contains(rect);

Early return.

> Source/WebCore/rendering/RenderImage.cpp:436
> +    return fullyContainQueryRect && imageIsOpaque;

This method will do the wrong thing in cases where the image doesn't fill the entire contentsBox. That can happen for SVG images with intrinsic aspect ratio, and will happen in future when we implement object-fit. I think you should compute the image destination rect like RenderImage::paintReplaced() does, and check that against 'rect', and add a comment about object-fit.

> Source/WebCore/rendering/RenderImage.cpp:452
> +    return foregroundContentsAreOpaqueInRect(borderBoundingBox());

I think you should change the caller of backgroundIsObscured() to use your new methods, maybe in a followup patch.

> Source/WebCore/rendering/RenderLayerBacking.cpp:195
> +    Vector<IntRect> opaqueRegions;

This is where you could use a Region, right?

> Source/WebCore/rendering/RenderObject.h:741
> +    // Returns true if the foreground within the query rect will be filled completely opaque by the RenderObject.

"filled completely opaque"  is not correct English. "filled opaquely" would be better.

> LayoutTests/compositing/opaque/borders.html:1
> +<!DOCTYPE html>

I think you need to test a lot more combinations of border, padding, image content etc.
Comment 49 Dana Jansens 2011-11-15 15:11:58 PST
(In reply to comment #48)
> (From update of attachment 114960 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=114960&action=review
> 
> > Source/WebCore/rendering/RenderBoxModelObject.cpp:2673
> > +bool RenderBoxModelObject::backgroundContentsAreOpaqueInRect(const IntRect& rect) const
> 
> 'contents' in the name makes me wonder if this method checks the contentBox only, which it does not. I think backgroundIsOpaqueInRect is better.

It was meant to check only the content box. Thanks for noticing this discrepancy. I think this will be much more consistent and clear in the next patch by checking instead in isOpaqueInRect().

I'm moving the method to RenderBox (this is where your methods lived as well) so that it can determine the content box properly. And moving the top level virtual declarations down to RenderBoxModelObject since concepts like borderBoundingBox() don't exist above that. boxDecorationAreaIsOpaque only really makes sense on a RBMO, for example.

> Why not check for alpha in background images?

Judging from maskClipRect, this looks like it will be complicated, requiring at least a walk through the style's FillLayers, determining which are opaque, and then if their regions cover the query rect. I think this should come in another CL? Added a FIXME.

> > Source/WebCore/rendering/RenderBoxModelObject.cpp:2682
> > +    const bool fullyContainQueryRect = bounds.contains(rect);
> 
> Why not early 'return false' here?

The function used to be a set of false early-outs, but I removed them to make false the default return instead. I can early out here again.

> > Source/WebCore/rendering/RenderBoxModelObject.cpp:2689
> > +    const Color bgColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
> > +    const bool bgColorIsOpaque = bgColor.isValid() && !bgColor.hasAlpha();
> 
> We don't normally use const on local variables.

ok.

> > Source/WebCore/rendering/RenderBoxModelObject.cpp:2694
> > +bool RenderBoxModelObject::boxDecorationsAreOpaqueInRect(const IntRect& rect) const
> 
> I think a better blame would be boxDecorationAreaIsOpaqueInRect().

ok.

> > Source/WebCore/rendering/RenderBoxModelObject.cpp:2699
> > +    // If the query rect leaves the render object, then we can't vouch that the entire rect is opaque.
> > +    const bool fullyContainQueryRect = bounds.contains(rect);
> 
> You should early return here to avoid all the extra work later in the method.

ok.

> > Source/WebCore/rendering/RenderBoxModelObject.cpp:2711
> > +    const LayoutRect contentsBounds(bounds.x() + borderLeft() + paddingLeft(),
> > +                                    bounds.y() + borderTop() + paddingTop(),
> > +                                    bounds.width() - borderLeft() - borderRight() - paddingLeft() - paddingRight(),
> > +                                    bounds.height() - borderTop() - borderBottom() - paddingTop() - paddingBottom());
> 
> I'm surprised we don't have method that does this already.

RenderBox does, which is a better place for these methods anyhow.  RenderInline should consider each line independently, and can do so using Regions once that code lands.

> > Source/WebCore/rendering/RenderBoxModelObject.cpp:2712
> > +    const bool contentsFullyContainQueryRect = contentsBounds.contains(rect);
> 
> Another opportunity for an early return?

sure.

> > Source/WebCore/rendering/RenderBoxModelObject.cpp:2736
> > +        // If the above for loop completed, then all borders obscure the background.
> > +        if (i > BSLeft)
> > +            bordersOpaque = true;
> 
> It would be clearer just to set a flag from within the loop (then you can make i a variable with loop scope).

ok.

> A future optimization could only look at the borders that intersect 'rect', also. Add a FIXME comment?

ok.

> > Source/WebCore/rendering/RenderBoxModelObject.cpp:2745
> > +
> > +
> 
> Two blank lines.

fixed.

> > Source/WebCore/rendering/RenderImage.cpp:418
> > +    const bool fullyContainQueryRect = bounds.contains(rect);
> 
> Early return.

ok.

> > Source/WebCore/rendering/RenderImage.cpp:436
> > +    return fullyContainQueryRect && imageIsOpaque;
> 
> This method will do the wrong thing in cases where the image doesn't fill the entire contentsBox. That can happen for SVG images with intrinsic aspect ratio, and will happen in future when we implement object-fit. I think you should compute the image destination rect like RenderImage::paintReplaced() does, and check that against 'rect', and add a comment about object-fit.

Great, thanks for this pointer. Added this check.

> > Source/WebCore/rendering/RenderImage.cpp:452
> > +    return foregroundContentsAreOpaqueInRect(borderBoundingBox());
> 
> I think you should change the caller of backgroundIsObscured() to use your new methods, maybe in a followup patch.

Sounds good. Bug #72412.

> > Source/WebCore/rendering/RenderLayerBacking.cpp:195
> > +    Vector<IntRect> opaqueRegions;
> 
> This is where you could use a Region, right?

Yes. Bug #72298 will do this.

> > Source/WebCore/rendering/RenderObject.h:741
> > +    // Returns true if the foreground within the query rect will be filled completely opaque by the RenderObject.
> 
> "filled completely opaque"  is not correct English. "filled opaquely" would be better.

ok.

> > LayoutTests/compositing/opaque/borders.html:1
> > +<!DOCTYPE html>
> 
> I think you need to test a lot more combinations of border, padding, image content etc.

Will add more, coming soon. Patch incoming with the other above changes in the meantime.

Thanks.
Comment 50 Dana Jansens 2011-11-15 15:13:11 PST
Created attachment 115261 [details]
Patch
Comment 51 Dana Jansens 2011-11-18 07:47:51 PST
Created attachment 115808 [details]
Patch
Comment 52 Dana Jansens 2011-11-18 07:49:55 PST
Added a bunch of tests to borders.html.

- Test combinations of opaque/transparent borders, padding, background-clip, opaque-transparent background colors.
- Tests that it catches javascript changing css properties.
- Tests images with/without alpha, and with borders/padding.

Do these look sufficient for this step?
Comment 53 WebKit Review Bot 2011-11-18 08:24:09 PST
Comment on attachment 115808 [details]
Patch

Attachment 115808 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/10519129

New failing tests:
compositing/geometry/limit-layer-bounds-transformed.html
compositing/iframes/enter-compositing-iframe.html
compositing/iframes/connect-compositing-iframe.html
compositing/geometry/clip.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/limit-layer-bounds-positioned.html
compositing/layer-creation/overlap-child-layer.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
compositing/layer-creation/overlap-transformed-layer.html
compositing/layer-creation/translatez-overlap.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/limit-layer-bounds-overflow-root.html
compositing/layer-creation/spanOverlapsCanvas.html
compositing/geometry/limit-layer-bounds-clipping-ancestor.html
compositing/layer-creation/overlap-clipping.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/layer-creation/overflow-scroll-overlap.html
Comment 54 WebKit Review Bot 2011-11-18 08:24:16 PST
Created attachment 115815 [details]
Archive of layout-test-results from ec2-cr-linux-03

The attached test failures were seen while running run-webkit-tests on the chromium-ews.
Bot: ec2-cr-linux-03  Port: Chromium  Platform: Linux-2.6.35-28-virtual-x86_64-with-Ubuntu-10.10-maverick
Comment 55 Dana Jansens 2011-11-21 08:06:17 PST
Created attachment 116092 [details]
Column rules are in contents area background.
Comment 56 WebKit Review Bot 2011-11-21 10:33:03 PST
Comment on attachment 116092 [details]
Column rules are in contents area background.

Attachment 116092 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/10378497

New failing tests:
compositing/geometry/limit-layer-bounds-transformed.html
compositing/iframes/enter-compositing-iframe.html
compositing/iframes/connect-compositing-iframe.html
compositing/geometry/clip.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/limit-layer-bounds-positioned.html
compositing/layer-creation/overlap-child-layer.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
compositing/layer-creation/overlap-transformed-layer.html
compositing/layer-creation/translatez-overlap.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/limit-layer-bounds-overflow-root.html
compositing/layer-creation/spanOverlapsCanvas.html
compositing/geometry/limit-layer-bounds-clipping-ancestor.html
compositing/layer-creation/overlap-clipping.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/layer-creation/overflow-scroll-overlap.html
Comment 57 Dana Jansens 2011-11-22 10:22:56 PST
Created attachment 116240 [details]
Remove chromium specific things
Comment 58 Dana Jansens 2011-11-22 11:05:50 PST
Created attachment 116251 [details]
Remove tests of directly composited images
Comment 59 Dana Jansens 2011-11-22 11:09:34 PST
With composited <img> tags, the backing uses GraphicsLayer::setContentsToImage() rather than the general code-path.  Opaque-ness needs to be tested in the GraphicsLayer subclass.

In order to test opaque RenderImage objects, we need the image to be a child of a composited object.  This patch doesn't consider child RenderObjects so we can't test them just yet.  I've created tests for them in the next-step edition.
Comment 60 Dana Jansens 2011-11-22 12:09:15 PST
(In reply to comment #59)
> With composited <img> tags, the backing uses GraphicsLayer::setContentsToImage() rather than the general code-path.  Opaque-ness needs to be tested in the GraphicsLayer subclass.
> 
> In order to test opaque RenderImage objects, we need the image to be a child of a composited object.  This patch doesn't consider child RenderObjects so we can't test them just yet.  I've created tests for them in the next-step edition.

Sorry for the noise. I see that RenderImage objects are used for composited <img> tags when they have a border/padding/etc.  So adding tests in here for images with borders/padding/etc.

As noted by the bots, this will break some existing LayoutTests due to them now have opaque stuff.  I've never dealt with this before and would appreciate some guidance on this process. Should I be resetting results in those tests in this CL? Should I make a follow up CL with the reset?
Comment 61 Dana Jansens 2011-11-22 12:13:54 PST
Created attachment 116261 [details]
Patch
Comment 62 WebKit Review Bot 2011-11-23 02:16:05 PST
Comment on attachment 116261 [details]
Patch

Attachment 116261 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/10608256

New failing tests:
compositing/geometry/limit-layer-bounds-transformed.html
compositing/iframes/enter-compositing-iframe.html
compositing/iframes/connect-compositing-iframe.html
compositing/geometry/clip.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/limit-layer-bounds-positioned.html
compositing/layer-creation/overlap-child-layer.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
compositing/layer-creation/overlap-transformed-layer.html
compositing/layer-creation/translatez-overlap.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/limit-layer-bounds-overflow-root.html
compositing/layer-creation/spanOverlapsCanvas.html
compositing/geometry/limit-layer-bounds-clipping-ancestor.html
compositing/layer-creation/overlap-clipping.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/layer-creation/overflow-scroll-overlap.html
Comment 63 WebKit Review Bot 2011-11-23 02:16:11 PST
Created attachment 116332 [details]
Archive of layout-test-results from ec2-cr-linux-03

The attached test failures were seen while running run-webkit-tests on the chromium-ews.
Bot: ec2-cr-linux-03  Port: Chromium  Platform: Linux-2.6.35-28-virtual-x86_64-with-Ubuntu-10.10-maverick
Comment 64 Dana Jansens 2011-11-23 12:11:17 PST
Rather than creating this Transformation::isAxisAligned business, we can use the transformation on the bounding box, and test if the result is rectilinear. This is a more reliable test and doesn't require new code.
Comment 65 Dana Jansens 2011-11-23 12:42:10 PST
Created attachment 116403 [details]
Patch
Comment 66 WebKit Review Bot 2011-11-23 13:34:23 PST
Comment on attachment 116403 [details]
Patch

Attachment 116403 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/10633071

New failing tests:
compositing/geometry/limit-layer-bounds-transformed.html
compositing/geometry/clip.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/limit-layer-bounds-positioned.html
compositing/iframes/composited-parent-iframe.html
compositing/geometry/layer-due-to-layer-children.html
compositing/iframes/become-overlapped-iframe.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/layer-creation/overlap-clipping.html
compositing/geometry/layer-due-to-layer-children-switch.html
compositing/geometry/limit-layer-bounds-clipping-ancestor.html
compositing/geometry/layer-due-to-layer-children-deep.html
compositing/layer-creation/overlap-child-layer.html
compositing/geometry/preserve-3d-switching.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/geometry/limit-layer-bounds-overflow-root.html
compositing/layer-creation/overflow-scroll-overlap.html
Comment 67 Dana Jansens 2011-11-24 15:18:59 PST
Created attachment 116550 [details]
Patch
Comment 68 Dana Jansens 2011-11-24 15:21:21 PST
The LayoutTests with images were coming across as flakey because sometimes the composited bounds would be computed before the images were loaded. When the image is loaded/changed, it needs to redecide if it is opaque or not.

Small change to the patch to make RenderLayerBacking::contentChanged recompute the contentsOpaque flag when it won't be via recomputing bounds.
Comment 69 WebKit Review Bot 2011-11-27 01:31:43 PST
Comment on attachment 116550 [details]
Patch

Attachment 116550 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/10669157

New failing tests:
compositing/iframes/enter-compositing-iframe.html
compositing/iframes/connect-compositing-iframe.html
compositing/geometry/clip.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/layer-due-to-layer-children-switch.html
compositing/iframes/composited-parent-iframe.html
compositing/geometry/layer-due-to-layer-children.html
compositing/iframes/become-overlapped-iframe.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
compositing/iframes/connect-compositing-iframe-delayed.html
animations/missing-from-to-transforms.html
compositing/geometry/limit-layer-bounds-clipping-ancestor.html
compositing/geometry/layer-due-to-layer-children-deep.html
compositing/animation/computed-style-during-delay.html
compositing/iframes/connect-compositing-iframe2.html
compositing/iframes/connect-compositing-iframe3.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/geometry/limit-layer-bounds-overflow-root.html
Comment 70 Dana Jansens 2011-11-28 06:41:13 PST
Comment on attachment 116550 [details]
Patch

This patch has some bad effects with WebGL Canvas. In particular, when an image contents change, we need to determine its opaque status for the RenderLayer's opaque region. But in order to create an Image* for a generated image, the contents may change causing a loop where there should not be. This causes a synchronization issue in the HTMLCanvasElement/WebGL interaction, since it does not expect to generate an image in its contents changed listeners.
Comment 71 Dana Jansens 2011-11-28 09:07:07 PST
Created attachment 116768 [details]
notify backing about content changes in layers
Comment 72 WebKit Review Bot 2011-11-28 09:46:49 PST
Comment on attachment 116768 [details]
notify backing about content changes in layers

Attachment 116768 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/10675335

New failing tests:
compositing/iframes/enter-compositing-iframe.html
compositing/iframes/connect-compositing-iframe.html
compositing/geometry/clip.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/layer-due-to-layer-children-switch.html
compositing/iframes/composited-parent-iframe.html
compositing/geometry/layer-due-to-layer-children.html
compositing/iframes/become-overlapped-iframe.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
compositing/iframes/connect-compositing-iframe-delayed.html
animations/missing-from-to-transforms.html
compositing/geometry/limit-layer-bounds-clipping-ancestor.html
compositing/geometry/layer-due-to-layer-children-deep.html
compositing/animation/computed-style-during-delay.html
compositing/iframes/connect-compositing-iframe2.html
compositing/iframes/connect-compositing-iframe3.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/geometry/limit-layer-bounds-overflow-root.html
Comment 73 Simon Fraser (smfr) 2011-11-28 11:29:16 PST
The number of patches here is getting overwhelming. Can you do more local testing to avoid all the patch spam?
Comment 74 Dana Jansens 2011-11-28 11:32:44 PST
Sure, I can avoid uploading patches before feedback on the previous one.
Comment 75 Kenneth Russell 2011-11-28 13:17:35 PST
(In reply to comment #70)
> (From update of attachment 116550 [details])
> This patch has some bad effects with WebGL Canvas. In particular, when an image contents change, we need to determine its opaque status for the RenderLayer's opaque region. But in order to create an Image* for a generated image, the contents may change causing a loop where there should not be. This causes a synchronization issue in the HTMLCanvasElement/WebGL interaction, since it does not expect to generate an image in its contents changed listeners.

I haven't been watching this bug closely, but wanted to make it clear that it isn't feasible to determine whether WebGL content is completely opaque -- aside from seeing whether the WebGL context was created without an alpha channel. See http://www.khronos.org/registry/webgl/specs/latest/#5.2.1 . The assumption in the general case must be that WebGL content is not opaque. It would be fine to assume this all the time initially, and optimize it later. Please make sure that this patch does not introduce a CPU readback during WebGL rendering; this would kill performance.
Comment 76 Dana Jansens 2011-11-28 13:34:26 PST
(In reply to comment #75)
> (In reply to comment #70)
> > (From update of attachment 116550 [details] [details])
> > This patch has some bad effects with WebGL Canvas. In particular, when an image contents change, we need to determine its opaque status for the RenderLayer's opaque region. But in order to create an Image* for a generated image, the contents may change causing a loop where there should not be. This causes a synchronization issue in the HTMLCanvasElement/WebGL interaction, since it does not expect to generate an image in its contents changed listeners.
> 
> I haven't been watching this bug closely, but wanted to make it clear that it isn't feasible to determine whether WebGL content is completely opaque -- aside from seeing whether the WebGL context was created without an alpha channel. See http://www.khronos.org/registry/webgl/specs/latest/#5.2.1 . The assumption in the general case must be that WebGL content is not opaque. It would be fine to assume this all the time initially, and optimize it later. Please make sure that this patch does not introduce a CPU readback during WebGL rendering; this would kill performance.

Thanks for this. I will require some plumbing through the RenderImageResource to be able to tell if it is a WebGL image at all and avoid this readback.
Comment 77 Simon Fraser (smfr) 2011-11-28 13:39:26 PST
Why can't you just assume that all canvases are not opaque?
Comment 78 Kenneth Russell 2011-11-28 13:43:32 PST
(In reply to comment #77)
> Why can't you just assume that all canvases are not opaque?

That's a good assumption. Analyzing the contents of a Canvas rendered via any means is likely to impose a massive slowdown.
Comment 79 Dana Jansens 2011-11-28 13:50:19 PST
(In reply to comment #77)
> Why can't you just assume that all canvases are not opaque?

What I'm not seeing is a way to tell that a RenderImage is a canvas at all. Am I just missing it somewhere?

What I've seen is that the StyleImage class has an isGeneratedImage() which is true for a canvas. I was thinking to have

RenderImageResource::isGeneratedImage() { return false; }

and then RenderImageResourceStyleImage could override it and give something useful. And the opaque-check could just ignore generated images.

Side-note: it would be easier and cleaner to simply remove any changes to RenderImage.cpp from this bug and stick that in another one, would that be good for you Simon?
Comment 80 Simon Fraser (smfr) 2011-11-28 13:53:41 PST
Are you talking about -webkit-canvas (i.e. canvas in CSS)? Doesn't currentFrameHasAlpha() just do the right thing for that kind of image?
Comment 81 Dana Jansens 2011-11-28 14:06:22 PST
(In reply to comment #80)
> Are you talking about -webkit-canvas (i.e. canvas in CSS)? Doesn't currentFrameHasAlpha() just do the right thing for that kind of image?

I think so, the HTMLCanvasElement class.

I presume it would give the right value, but the problem is that currentFrameHasAlpha() is in the Image object.  And grabbing the Image object causes WebGL to paint, which we don't want to do in response to the image contentChanged notification.

Calling RenderImageResource::image() ends up calling:
- RenderImageResourceStyleImage::image()
- StyleGeneratedImage::image()
- CSSImageGeneratorValue::image()
- CSSCanvasValue::image()
- HTMLCanvasElement::copiedImage() which gets the WebGLRenderingContext to paint itself and caches the result.

From what I can see we need a way to see that it is a canvas/generated image without the above, in order to update the opaque region when image contents change.
Comment 82 Dana Jansens 2011-11-29 14:09:33 PST
Comment on attachment 116768 [details]
notify backing about content changes in layers

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

Not sure if this would help but I can imagine splitting this into a few smaller patches if you'd like. These are all somewhat independent pieces mashed together. If not at least we can talk about them somewhat independently.
1. RenderLayerCompositor builds opaque region for a backing (uses stub RenderLayer::opaqueRegion()), and backing decides opaque flag
2. RenderLayer::contentChanged() causes its compositing backing to re-decide opaque flag.
3. Add the *AreaIsOpaqueInRect() methods to RenderBox and RBMO.
4. Have RenderLayer::opaqueRegion() test its renderer() with RBMO::isOpaque().
5. Add foregroundContentsAreaIsOpaqueInRect() for RenderImage.

> Source/WebCore/rendering/RenderImage.cpp:437
> +            Image* image = m_imageResource->image(cWidth, cHeight).get();

This is the call we do not make for a canvas/webgl image when its contents are changed, as it causes a CPU readback.

> Source/WebCore/rendering/RenderLayer.h:470
> +    Region opaqueRegion() const { return renderer()->isOpaqueInRect(renderer()->borderBoundingBox()) ? renderer()->borderBoundingBox() : Region(); }

I can stick this behind #ifdef USE(ACCELERATED_COMPOSITING).
Comment 83 Simon Fraser (smfr) 2011-12-01 12:09:28 PST
*** Bug 40629 has been marked as a duplicate of this bug. ***
Comment 84 Dana Jansens 2011-12-05 11:22:32 PST
Created attachment 117907 [details]
Patch

@smfr, thanks for the conversation on Friday. I'm submitting a new patch that is more along the lines you described
on IRC. This considers only a single RenderObject for a backing in a simple way. It updates contentsOpaque when bounds
or content changed.

I experimented with just doing this computation during the painting step, but that made using DRT for testing it not
possible, as nothing showed up opaque there.

I've approached this with a better understanding of what "contents" means. This patch will check the background and
box decorations for a backing to see if they are opaque. If the background is not, then it will try the foreground, but
only if it will be painted (ie is part of the "contents"). If the foreground will be composited then it is not tested
here.

There are 3 sets of layout tests. One to test combinations or box decorations and backgrounds. One to test these same
things with composited image foregrounds. And one to test these together with painted image foregrounds.
Comment 85 WebKit Review Bot 2011-12-05 12:01:04 PST
Comment on attachment 117907 [details]
Patch

Attachment 117907 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/10732708

New failing tests:
compositing/geometry/limit-layer-bounds-transformed.html
compositing/layer-creation/overlap-transformed-layer.html
compositing/geometry/clip.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/limit-layer-bounds-positioned.html
compositing/iframes/composited-parent-iframe.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/iframes/become-overlapped-iframe.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
accessibility/aria-checkbox-text.html
compositing/layer-creation/overlap-clipping.html
compositing/geometry/layer-due-to-layer-children-switch.html
compositing/geometry/limit-layer-bounds-clipping-ancestor.html
compositing/iframes/connect-compositing-iframe2.html
compositing/layer-creation/overlap-child-layer.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/geometry/limit-layer-bounds-overflow-root.html
compositing/layer-creation/overflow-scroll-overlap.html
Comment 86 WebKit Review Bot 2011-12-05 12:01:10 PST
Created attachment 117909 [details]
Archive of layout-test-results from ec2-cr-linux-01

The attached test failures were seen while running run-webkit-tests on the chromium-ews.
Bot: ec2-cr-linux-01  Port: Chromium  Platform: Linux-2.6.35-28-virtual-x86_64-with-Ubuntu-10.10-maverick
Comment 87 Eric Seidel (no email) 2011-12-21 13:38:10 PST
This bug has gone epic.  It's going to be difficult to find reviewers for a 20 patch, 80+ comment bug.  I recommend attempting to break your work into smaller pieces and opening new bugs for those smaller pieces.
Comment 88 Nat Duca 2012-08-07 23:40:01 PDT
Dana, should we mark this wontfix since we found a different way to do this?
Comment 89 Simon Fraser (smfr) 2012-08-08 08:45:35 PDT
You did?
Comment 90 Dana Jansens 2012-08-08 09:06:06 PDT
Yes, though this could do a better job in some cases, we are watching the calls to GraphicsContext and tracking an opaque rect via that.

I don't think this is truly WontFix, as this could be beneficial too, especially to making painting faster. But am not planning on working on it any time soon either.
Comment 91 Simon Fraser (smfr) 2012-08-08 09:44:37 PDT
I presume that was Chromium only, so this bug is still valid for other platforms.
Comment 92 Dana Jansens 2012-08-08 09:52:53 PDT
Yep.
Comment 93 Alok Priyadarshi 2013-01-29 15:58:40 PST
Reviving this old thread. I would like to mark GraphicsLayers as opaque to enable LCD text. I have created a patch by stealing code from here and referenced bugs. I will upload it shortly and would appreciate early feedback on the overall approach.
Comment 94 Alok Priyadarshi 2013-01-29 16:28:38 PST
Created attachment 185337 [details]
Patch
Comment 95 WebKit Review Bot 2013-01-29 16:31:33 PST
Attachment 185337 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WebCore/rendering/RenderBox.cpp', u'Source/WebCore/rendering/RenderBox.h', u'Source/WebCore/rendering/RenderBoxModelObject.h', u'Source/WebCore/rendering/RenderLayer.cpp', u'Source/WebCore/rendering/RenderLayer.h', u'Source/WebCore/rendering/RenderLayerBacking.cpp', u'Source/WebCore/rendering/RenderLayerModelObject.h']" exit_code: 1
Source/WebCore/rendering/RenderLayer.cpp:5139:  Boolean expressions that span multiple lines should have their operators on the left side of the line instead of the right side.  [whitespace/operators] [4]
Source/WebCore/rendering/RenderLayer.cpp:5140:  Boolean expressions that span multiple lines should have their operators on the left side of the line instead of the right side.  [whitespace/operators] [4]
Source/WebCore/rendering/RenderLayer.cpp:5140:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Source/WebCore/rendering/RenderLayer.cpp:5141:  Boolean expressions that span multiple lines should have their operators on the left side of the line instead of the right side.  [whitespace/operators] [4]
Source/WebCore/rendering/RenderLayer.cpp:5141:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Source/WebCore/rendering/RenderLayer.cpp:5142:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Total errors found: 6 in 7 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 96 Simon Fraser (smfr) 2013-01-29 16:37:54 PST
Comment on attachment 185337 [details]
Patch

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

This needs a changelog and some tests, but it's a good start.

> Source/WebCore/rendering/RenderBox.cpp:1160
> +    Color backgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
> +    if (!backgroundColor.isValid() || backgroundColor.hasAlpha())
> +        return false;

You could also check the background images here.

> Source/WebCore/rendering/RenderBox.h:598
> +    virtual bool backgroundIsOpaqueInRect(const LayoutPoint&, const IntRect&) const OVERRIDE;

It's not clear why the first argument is needed here. What is it an offset relative to? The rect should just be passed in some agreed-upon coordinate system (e.g. relative to the border box).

> Source/WebCore/rendering/RenderBoxModelObject.h:89
> +    virtual bool isPaintedOpaqueInRect(const LayoutPoint& offset, const IntRect& rect) const OVERRIDE { return foregroundIsOpaqueInRect(offset, rect) || backgroundIsOpaqueInRect(offset, rect); }

I don't like "isPaintedOpaque".

> Source/WebCore/rendering/RenderLayer.cpp:5108
> +static bool isListPaintedOpaqueInRect(const Vector<RenderLayer*>* list, PaintBehavior paintBehavior, const RenderLayer* rootLayer, const IntRect& rect)

Very clumsy function name.

> Source/WebCore/rendering/RenderLayer.cpp:5142
> +    return renderer()->isPaintedOpaqueInRect(offset, rect) ||
> +           isListPaintedOpaqueInRect(m_posZOrderList.get(), paintBehavior, rootLayer, rect) ||
> +           isListPaintedOpaqueInRect(m_negZOrderList.get(), paintBehavior, rootLayer, rect) ||
> +           isListPaintedOpaqueInRect(m_normalFlowList.get(), paintBehavior, rootLayer, rect);

This is testing just the layer's immediate renderer, which is a reasonable start but you should add a FIXME that it will miss many cases.

> Source/WebCore/rendering/RenderLayer.h:721
> +    // Input rect is given in rootLayer's coordinate space.

Why not just local to this layer?
Comment 97 Alok Priyadarshi 2013-01-29 21:28:53 PST
Comment on attachment 185337 [details]
Patch

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

Simon: Thanks for the quick review. I will add tests and Changelog in the next patch. I wanted to get early feedback on the approach before investing too much time.

>> Source/WebCore/rendering/RenderBox.cpp:1160
>> +        return false;
> 
> You could also check the background images here.

I would prefer to do it in a separate patch. I will add a FIXME here.

>> Source/WebCore/rendering/RenderBox.h:598
>> +    virtual bool backgroundIsOpaqueInRect(const LayoutPoint&, const IntRect&) const OVERRIDE;
> 
> It's not clear why the first argument is needed here. What is it an offset relative to? The rect should just be passed in some agreed-upon coordinate system (e.g. relative to the border box).

I agree and that will in fact be cleaner. I was trying to keep it consistent with the RenderObject::paint() method which takes an offset parameter. May be I misunderstood your suggestion in comment 21 that you wanted the "isOpaque code mirror the painting code more closely".

>> Source/WebCore/rendering/RenderBoxModelObject.h:89
>> +    virtual bool isPaintedOpaqueInRect(const LayoutPoint& offset, const IntRect& rect) const OVERRIDE { return foregroundIsOpaqueInRect(offset, rect) || backgroundIsOpaqueInRect(offset, rect); }
> 
> I don't like "isPaintedOpaque".

What about isOpaqueInRect? Any other suggestions?

>> Source/WebCore/rendering/RenderLayer.cpp:5108
>> +static bool isListPaintedOpaqueInRect(const Vector<RenderLayer*>* list, PaintBehavior paintBehavior, const RenderLayer* rootLayer, const IntRect& rect)
> 
> Very clumsy function name.

How about listContentsOpaqueInRect? Any other suggestions?

> Source/WebCore/rendering/RenderLayer.cpp:5123
> +bool RenderLayer::isPaintedOpaqueInRect(PaintBehavior paintBehavior, const RenderLayer* rootLayer, const IntRect& rect) const

How about the function name contentsOpaqueInRect()?

>>> Source/WebCore/rendering/RenderLayer.cpp:5142
>>> +           isListPaintedOpaqueInRect(m_normalFlowList.get(), paintBehavior, rootLayer, rect);
>> 
>> Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
> 
> This is testing just the layer's immediate renderer, which is a reasonable start but you should add a FIXME that it will miss many cases.

Will do.

>> Source/WebCore/rendering/RenderLayer.h:721
>> +    // Input rect is given in rootLayer's coordinate space.
> 
> Why not just local to this layer?

Sure. I was trying to keep it consistent with the paint method. Will change if that is no longer desired.
Comment 98 Alok Priyadarshi 2013-02-05 14:56:58 PST
Created attachment 186713 [details]
Patch
Comment 99 Alok Priyadarshi 2013-02-05 14:58:04 PST
Added Tests and ChangeLog. Converted query-rect to local coordinates.
Comment 100 WebKit Review Bot 2013-02-05 15:40:21 PST
Comment on attachment 186713 [details]
Patch

Attachment 186713 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/16370923

New failing tests:
compositing/geometry/bounds-ignores-hidden.html
compositing/geometry/clip.html
compositing/geometry/limit-layer-bounds-positioned.html
compositing/absolute-inside-out-of-view-fixed.html
compositing/geometry/limit-layer-bounds-clipping-ancestor.html
compositing/backing/no-backing-for-clip-overlap.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/iframes/become-overlapped-iframe.html
compositing/filters/sw-shadow-overlaps-hw-layer.html
compositing/geometry/layer-due-to-layer-children-switch.html
compositing/geometry/preserve-3d-switching.html
compositing/geometry/bounds-ignores-hidden-composited-descendant.html
compositing/geometry/limit-layer-bounds-overflow-root.html
compositing/filters/sw-layer-overlaps-hw-shadow.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
compositing/geometry/clip-inside.html
compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
compositing/columns/composited-in-paginated.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/bounds-ignores-hidden-dynamic.html
compositing/geometry/limit-layer-bounds-transformed.html
compositing/clip-child-by-non-stacking-ancestor.html
compositing/iframes/composited-parent-iframe.html
compositing/geometry/flipped-writing-mode.html
compositing/overflow-trumps-transform-style.html
compositing/backing/no-backing-for-clip.html
compositing/backing/no-backing-for-perspective.html
Comment 101 Build Bot 2013-02-05 18:38:53 PST
Comment on attachment 186713 [details]
Patch

Attachment 186713 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://queues.webkit.org/results/16390022

New failing tests:
compositing/iframes/invisible-nested-iframe-hide.html
compositing/geometry/bounds-ignores-hidden.html
compositing/geometry/clip.html
compositing/contents-opaque/contents-opaque-background-color.html
compositing/iframes/enter-compositing-iframe.html
compositing/iframes/iframe-resize.html
compositing/geometry/bounds-ignores-hidden-composited-descendant.html
compositing/contents-opaque/contents-opaque-layer-transform.html
compositing/iframes/connect-compositing-iframe2.html
compositing/columns/composited-in-paginated.html
compositing/geometry/fixed-position-composited-switch.html
compositing/iframes/become-overlapped-iframe.html
compositing/filters/sw-shadow-overlaps-hw-layer.html
compositing/iframes/connect-compositing-iframe3.html
compositing/absolute-inside-out-of-view-fixed.html
compositing/tiled-layers-hidpi.html
compositing/filters/sw-layer-overlaps-hw-shadow.html
compositing/geometry/clip-inside.html
compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
compositing/iframes/connect-compositing-iframe.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/bounds-ignores-hidden-dynamic.html
compositing/contents-opaque/contents-opaque-layer-opacity.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/clip-child-by-non-stacking-ancestor.html
compositing/iframes/composited-parent-iframe.html
compositing/overflow-trumps-transform-style.html
compositing/backing/no-backing-for-clip.html
compositing/backing/no-backing-for-clip-overlap.html
compositing/backing/no-backing-for-perspective.html
Comment 102 Build Bot 2013-02-05 20:01:40 PST
Comment on attachment 186713 [details]
Patch

Attachment 186713 [details] did not pass win-ews (win):
Output: http://queues.webkit.org/results/16388085
Comment 103 Build Bot 2013-02-05 21:57:17 PST
Comment on attachment 186713 [details]
Patch

Attachment 186713 [details] did not pass win-ews (win):
Output: http://queues.webkit.org/results/16392054
Comment 104 Build Bot 2013-02-06 01:36:17 PST
Comment on attachment 186713 [details]
Patch

Attachment 186713 [details] did not pass mac-ews (mac):
Output: http://queues.webkit.org/results/16390167

New failing tests:
compositing/geometry/bounds-ignores-hidden.html
compositing/geometry/clip.html
compositing/contents-opaque/contents-opaque-background-color.html
compositing/layer-creation/fixed-position-and-transform.html
compositing/geometry/bounds-ignores-hidden-composited-descendant.html
compositing/contents-opaque/contents-opaque-layer-transform.html
compositing/backing/no-backing-for-clip-overlap.html
compositing/columns/composited-in-paginated.html
compositing/layer-creation/fixed-position-change-out-of-view-in-view.html
compositing/iframes/become-overlapped-iframe.html
compositing/filters/sw-shadow-overlaps-hw-layer.html
compositing/iframes/connect-compositing-iframe3.html
compositing/absolute-inside-out-of-view-fixed.html
compositing/tiled-layers-hidpi.html
compositing/filters/sw-layer-overlaps-hw-shadow.html
compositing/iframes/enter-compositing-iframe.html
compositing/geometry/clip-inside.html
compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
compositing/iframes/connect-compositing-iframe.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/bounds-ignores-hidden-dynamic.html
compositing/contents-opaque/contents-opaque-layer-opacity.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/clip-child-by-non-stacking-ancestor.html
compositing/iframes/composited-parent-iframe.html
compositing/overflow-trumps-transform-style.html
compositing/backing/no-backing-for-clip.html
compositing/iframes/connect-compositing-iframe2.html
compositing/backing/no-backing-for-perspective.html
compositing/layer-creation/animation-overlap-with-children.html
Comment 105 Alok Priyadarshi 2013-02-06 09:54:59 PST
The reason so many tests are failing because tests use opaque background for composited layers. I am going through each failure and making sure that the new baselines are correct.
Comment 106 Alok Priyadarshi 2013-02-06 15:46:49 PST
I manually examined all failing tests on cr-linux. All of them just need new rebaselines. The layers that are now marked opaque should indeed be marked opaque.

I suspected the results for compositing/geometry/flipped-writing-mode.html, but noticed that renderer background-rect does not cover the whole graphics-layer. So  the results are correct. But I wonder if I still need to call flipForWritingMode  to convert a rect in layer coordinates to that in renderer's local space.
Comment 107 Simon Fraser (smfr) 2013-02-07 11:14:06 PST
Comment on attachment 186713 [details]
Patch

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

> Source/WebCore/rendering/RenderLayer.cpp:5124
> +        || listContentsOpaqueInRect(m_posZOrderList.get(), localRect)
> +        || listContentsOpaqueInRect(m_negZOrderList.get(), localRect)
> +        || listContentsOpaqueInRect(m_normalFlowList.get(), localRect);

These should use the accessors (posZOrderList() etc), which will assert if the lists are stale.

> Source/WebCore/rendering/RenderLayer.cpp:5139
> +        childLayer->convertToLayerCoords(this, childOffset);

convertToLayerCoords() doesn't handle transforms, so it's a bit weird to always use it to convert the rect, then rely on the fact that contentsOpaqueInRect() bails if there's a transform.
Comment 108 Alok Priyadarshi 2013-02-07 11:43:43 PST
Comment on attachment 186713 [details]
Patch

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

>> Source/WebCore/rendering/RenderLayer.cpp:5124
>> +        || listContentsOpaqueInRect(m_normalFlowList.get(), localRect);
> 
> These should use the accessors (posZOrderList() etc), which will assert if the lists are stale.

will do.

>> Source/WebCore/rendering/RenderLayer.cpp:5139
>> +        childLayer->convertToLayerCoords(this, childOffset);
> 
> convertToLayerCoords() doesn't handle transforms, so it's a bit weird to always use it to convert the rect, then rely on the fact that contentsOpaqueInRect() bails if there's a transform.

so is this sufficient?:
if (!childLayer->canUseConvertToLayerCoords()) continue;

sorry I am still learning about render-tree.
Comment 109 Alok Priyadarshi 2013-02-07 13:17:57 PST
Created attachment 187160 [details]
Patch
Comment 110 Build Bot 2013-02-07 15:44:45 PST
Comment on attachment 187160 [details]
Patch

Attachment 187160 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://queues.webkit.org/results/16408485

New failing tests:
compositing/iframes/invisible-nested-iframe-hide.html
compositing/geometry/bounds-ignores-hidden.html
compositing/geometry/clip.html
compositing/contents-opaque/contents-opaque-background-color.html
compositing/iframes/enter-compositing-iframe.html
compositing/iframes/iframe-resize.html
compositing/geometry/bounds-ignores-hidden-composited-descendant.html
compositing/contents-opaque/contents-opaque-layer-transform.html
compositing/iframes/connect-compositing-iframe2.html
compositing/columns/composited-in-paginated.html
compositing/geometry/fixed-position-composited-switch.html
compositing/iframes/become-overlapped-iframe.html
compositing/filters/sw-shadow-overlaps-hw-layer.html
compositing/iframes/connect-compositing-iframe3.html
compositing/tiled-layers-hidpi.html
compositing/filters/sw-layer-overlaps-hw-shadow.html
compositing/geometry/clip-inside.html
compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
compositing/iframes/connect-compositing-iframe.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/bounds-ignores-hidden-dynamic.html
compositing/contents-opaque/contents-opaque-layer-opacity.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/clip-child-by-non-stacking-ancestor.html
compositing/iframes/composited-parent-iframe.html
compositing/overflow-trumps-transform-style.html
compositing/backing/no-backing-for-clip.html
compositing/backing/no-backing-for-clip-overlap.html
compositing/backing/no-backing-for-perspective.html
Comment 111 Simon Fraser (smfr) 2013-02-07 15:49:54 PST
Comment on attachment 187160 [details]
Patch

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

> Source/WebCore/ChangeLog:8
> +        Mark layers as opaque in a very simple case - any child renderer has an opaque background and covers the entire composited bounds. RenderLayer::contentsOpaqueInRect has been implemented conservatively, i.e. it errs towards returning false negative.

It's not "any child renderer" currently; it's just the layer's main renderer.
Comment 112 Build Bot 2013-02-07 17:44:00 PST
Comment on attachment 187160 [details]
Patch

Attachment 187160 [details] did not pass mac-ews (mac):
Output: http://queues.webkit.org/results/16443391

New failing tests:
compositing/geometry/bounds-ignores-hidden.html
compositing/geometry/clip.html
compositing/contents-opaque/contents-opaque-background-color.html
compositing/layer-creation/fixed-position-and-transform.html
compositing/geometry/bounds-ignores-hidden-composited-descendant.html
compositing/contents-opaque/contents-opaque-layer-transform.html
compositing/backing/no-backing-for-clip-overlap.html
compositing/columns/composited-in-paginated.html
compositing/layer-creation/fixed-position-change-out-of-view-in-view.html
compositing/iframes/become-overlapped-iframe.html
compositing/filters/sw-shadow-overlaps-hw-layer.html
compositing/iframes/connect-compositing-iframe3.html
compositing/absolute-inside-out-of-view-fixed.html
compositing/tiled-layers-hidpi.html
compositing/filters/sw-layer-overlaps-hw-shadow.html
compositing/iframes/enter-compositing-iframe.html
compositing/geometry/clip-inside.html
compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
compositing/iframes/connect-compositing-iframe.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/bounds-ignores-hidden-dynamic.html
compositing/contents-opaque/contents-opaque-layer-opacity.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/clip-child-by-non-stacking-ancestor.html
compositing/iframes/composited-parent-iframe.html
compositing/overflow-trumps-transform-style.html
compositing/backing/no-backing-for-clip.html
compositing/iframes/connect-compositing-iframe2.html
compositing/backing/no-backing-for-perspective.html
compositing/layer-creation/animation-overlap-with-children.html
Comment 113 Alok Priyadarshi 2013-02-07 23:19:30 PST
Created attachment 187244 [details]
updated baselines
Comment 114 WebKit Review Bot 2013-02-08 00:45:33 PST
Comment on attachment 187244 [details]
updated baselines

Attachment 187244 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/16429511

New failing tests:
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view-scaled.html
platform/chromium/compositing/rounded-corners.html
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view.html
platform/chromium/virtual/softwarecompositing/rtl/rtl-iframe-fixed.html
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-change-out-of-view-in-view.html
platform/chromium/virtual/softwarecompositing/rtl/rtl-iframe-absolute.html
platform/chromium/virtual/softwarecompositing/rtl/rtl-fixed-overflow-scrolled.html
platform/chromium/virtual/softwarecompositing/rtl/rtl-iframe-relative.html
Comment 115 WebKit Review Bot 2013-02-08 01:23:41 PST
Comment on attachment 187244 [details]
updated baselines

Attachment 187244 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/16426573

New failing tests:
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view-scaled.html
platform/chromium/compositing/rounded-corners.html
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view.html
platform/chromium/virtual/softwarecompositing/rtl/rtl-iframe-fixed.html
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-change-out-of-view-in-view.html
platform/chromium/virtual/softwarecompositing/rtl/rtl-iframe-absolute.html
platform/chromium/virtual/softwarecompositing/rtl/rtl-fixed-overflow-scrolled.html
platform/chromium/virtual/softwarecompositing/rtl/rtl-iframe-relative.html
Comment 116 Build Bot 2013-02-08 01:56:30 PST
Comment on attachment 187244 [details]
updated baselines

Attachment 187244 [details] did not pass mac-ews (mac):
Output: http://queues.webkit.org/results/16415665

New failing tests:
compositing/contents-opaque/contents-opaque-background-color.html
compositing/layer-creation/fixed-position-and-transform.html
compositing/iframes/iframe-resize.html
compositing/geometry/bounds-ignores-hidden-composited-descendant.html
compositing/layer-creation/fixed-position-out-of-view.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/backing/no-backing-for-clip-overlap.html
compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html
compositing/columns/composited-in-paginated.html
compositing/geometry/fixed-position-composited-switch.html
compositing/layer-creation/fixed-position-out-of-view-scaled.html
compositing/layer-creation/fixed-position-change-out-of-view-in-view.html
compositing/iframes/become-overlapped-iframe.html
compositing/filters/sw-shadow-overlaps-hw-layer.html
compositing/iframes/connect-compositing-iframe3.html
compositing/tiled-layers-hidpi.html
compositing/filters/sw-layer-overlaps-hw-shadow.html
compositing/iframes/enter-compositing-iframe.html
compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
compositing/iframes/connect-compositing-iframe.html
compositing/iframes/become-composited-nested-iframes.html
compositing/contents-opaque/contents-opaque-layer-opacity.html
compositing/contents-opaque/contents-opaque-layer-transform.html
compositing/iframes/composited-parent-iframe.html
compositing/geometry/flipped-writing-mode.html
compositing/overflow-trumps-transform-style.html
compositing/backing/no-backing-for-clip.html
compositing/iframes/connect-compositing-iframe2.html
compositing/backing/no-backing-for-perspective.html
compositing/layer-creation/animation-overlap-with-children.html
Comment 117 Alok Priyadarshi 2013-02-08 16:22:23 PST
Created attachment 187383 [details]
another try to rebaseline
Comment 118 Build Bot 2013-02-08 17:32:01 PST
Comment on attachment 187244 [details]
updated baselines

Attachment 187244 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://queues.webkit.org/results/16427930

New failing tests:
compositing/contents-opaque/contents-opaque-background-color.html
compositing/iframes/enter-compositing-iframe.html
compositing/geometry/limit-layer-bounds-positioned.html
compositing/iframes/iframe-resize.html
compositing/geometry/bounds-ignores-hidden-composited-descendant.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/backing/no-backing-for-clip-overlap.html
compositing/columns/composited-in-paginated.html
compositing/geometry/fixed-position-composited-switch.html
compositing/iframes/become-overlapped-iframe.html
compositing/filters/sw-shadow-overlaps-hw-layer.html
compositing/iframes/connect-compositing-iframe3.html
compositing/geometry/limit-layer-bounds-overflow-root.html
compositing/tiled-layers-hidpi.html
compositing/filters/sw-layer-overlaps-hw-shadow.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
compositing/iframes/connect-compositing-iframe.html
compositing/iframes/become-composited-nested-iframes.html
compositing/contents-opaque/contents-opaque-layer-opacity.html
compositing/contents-opaque/contents-opaque-layer-transform.html
compositing/iframes/composited-parent-iframe.html
compositing/geometry/flipped-writing-mode.html
compositing/overflow-trumps-transform-style.html
compositing/backing/no-backing-for-clip.html
compositing/iframes/connect-compositing-iframe2.html
compositing/backing/no-backing-for-perspective.html
compositing/layer-creation/animation-overlap-with-children.html
Comment 119 Build Bot 2013-02-08 21:42:17 PST
Comment on attachment 187383 [details]
another try to rebaseline

Attachment 187383 [details] did not pass mac-ews (mac):
Output: http://queues.webkit.org/results/16466141

New failing tests:
compositing/iframes/scrolling-iframe.html
compositing/visible-rect/3d-transform-style.html
compositing/contents-opaque/contents-opaque-background-color.html
compositing/iframes/enter-compositing-iframe.html
compositing/iframes/iframe-resize.html
compositing/visible-rect/2d-transformed.html
compositing/iframes/invisible-nested-iframe-show.html
compositing/contents-opaque/contents-opaque-layer-transform.html
compositing/iframes/connect-compositing-iframe2.html
compositing/visible-rect/3d-transformed.html
compositing/visible-rect/animated-from-none.html
compositing/iframes/overlapped-iframe.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/iframes/become-overlapped-iframe.html
compositing/iframes/page-cache-layer-tree.html
compositing/iframes/connect-compositing-iframe3.html
compositing/tiled-layers-hidpi.html
compositing/visible-rect/clipped-by-viewport.html
compositing/plugins/no-backing-store.html
compositing/iframes/connect-compositing-iframe.html
compositing/layer-creation/overflow-scroll-overlap.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/iframes/composited-parent-iframe.html
compositing/visible-rect/clipped-visible-rect.html
compositing/contents-opaque/contents-opaque-layer-opacity.html
compositing/visible-rect/animated.html
compositing/iframes/resizer.html
compositing/layer-creation/animation-overlap-with-children.html
compositing/visible-rect/iframe-and-layers.html
Comment 120 Build Bot 2013-02-08 22:13:48 PST
Comment on attachment 187383 [details]
another try to rebaseline

Attachment 187383 [details] did not pass mac-ews (mac):
Output: http://queues.webkit.org/results/16473064

New failing tests:
compositing/iframes/scrolling-iframe.html
compositing/visible-rect/3d-transform-style.html
compositing/contents-opaque/contents-opaque-background-color.html
compositing/iframes/enter-compositing-iframe.html
compositing/iframes/iframe-resize.html
compositing/visible-rect/2d-transformed.html
compositing/iframes/invisible-nested-iframe-show.html
compositing/contents-opaque/contents-opaque-layer-transform.html
compositing/iframes/connect-compositing-iframe2.html
compositing/visible-rect/3d-transformed.html
compositing/visible-rect/animated-from-none.html
compositing/iframes/overlapped-iframe.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/iframes/become-overlapped-iframe.html
compositing/iframes/page-cache-layer-tree.html
compositing/iframes/connect-compositing-iframe3.html
compositing/tiled-layers-hidpi.html
compositing/visible-rect/clipped-by-viewport.html
compositing/plugins/no-backing-store.html
compositing/iframes/connect-compositing-iframe.html
compositing/layer-creation/overflow-scroll-overlap.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/iframes/composited-parent-iframe.html
compositing/visible-rect/clipped-visible-rect.html
compositing/contents-opaque/contents-opaque-layer-opacity.html
compositing/visible-rect/animated.html
compositing/iframes/resizer.html
compositing/layer-creation/animation-overlap-with-children.html
compositing/visible-rect/iframe-and-layers.html
Comment 121 Alok Priyadarshi 2013-02-08 23:08:56 PST
Created attachment 187420 [details]
Avoided assert and rebaselined platform/chromium
Comment 122 Build Bot 2013-02-09 01:48:05 PST
Comment on attachment 187420 [details]
Avoided assert and rebaselined platform/chromium

Attachment 187420 [details] did not pass mac-ews (mac):
Output: http://queues.webkit.org/results/16476174

New failing tests:
compositing/iframes/scrolling-iframe.html
compositing/visible-rect/3d-transform-style.html
compositing/contents-opaque/contents-opaque-background-color.html
compositing/iframes/enter-compositing-iframe.html
compositing/iframes/iframe-resize.html
compositing/visible-rect/2d-transformed.html
compositing/iframes/invisible-nested-iframe-show.html
compositing/contents-opaque/contents-opaque-layer-transform.html
compositing/iframes/connect-compositing-iframe2.html
compositing/visible-rect/3d-transformed.html
compositing/visible-rect/animated-from-none.html
compositing/iframes/overlapped-iframe.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/iframes/become-overlapped-iframe.html
compositing/iframes/page-cache-layer-tree.html
compositing/iframes/connect-compositing-iframe3.html
compositing/tiled-layers-hidpi.html
compositing/visible-rect/clipped-by-viewport.html
compositing/plugins/no-backing-store.html
compositing/iframes/connect-compositing-iframe.html
compositing/layer-creation/overflow-scroll-overlap.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/iframes/composited-parent-iframe.html
compositing/visible-rect/clipped-visible-rect.html
compositing/contents-opaque/contents-opaque-layer-opacity.html
compositing/visible-rect/animated.html
compositing/iframes/resizer.html
compositing/layer-creation/animation-overlap-with-children.html
compositing/visible-rect/iframe-and-layers.html
Comment 123 Build Bot 2013-02-09 06:59:50 PST
Comment on attachment 187420 [details]
Avoided assert and rebaselined platform/chromium

Attachment 187420 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://queues.webkit.org/results/16466429

New failing tests:
compositing/iframes/scrolling-iframe.html
compositing/visible-rect/3d-transform-style.html
compositing/contents-opaque/contents-opaque-background-color.html
compositing/iframes/enter-compositing-iframe.html
compositing/iframes/iframe-resize.html
compositing/visible-rect/2d-transformed.html
compositing/contents-opaque/contents-opaque-layer-transform.html
compositing/rtl/rtl-fixed-overflow.html
compositing/iframes/connect-compositing-iframe2.html
compositing/visible-rect/3d-transformed.html
compositing/visible-rect/animated-from-none.html
compositing/iframes/overlapped-iframe.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/iframes/become-overlapped-iframe.html
compositing/iframes/page-cache-layer-tree.html
compositing/rtl/rtl-fixed.html
compositing/iframes/connect-compositing-iframe3.html
compositing/tiled-layers-hidpi.html
compositing/tiling/tile-cache-zoomed.html
compositing/plugins/no-backing-store.html
compositing/iframes/connect-compositing-iframe.html
compositing/layer-creation/overflow-scroll-overlap.html
compositing/iframes/connect-compositing-iframe-delayed.html
compositing/iframes/composited-parent-iframe.html
compositing/iframes/invisible-nested-iframe-show.html
compositing/contents-opaque/contents-opaque-layer-opacity.html
compositing/visible-rect/animated.html
compositing/iframes/resizer.html
compositing/layer-creation/animation-overlap-with-children.html
Comment 124 WebKit Review Bot 2013-02-09 12:57:13 PST
Comment on attachment 187420 [details]
Avoided assert and rebaselined platform/chromium

Attachment 187420 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/16470479

New failing tests:
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view-scaled.html
platform/chromium/compositing/rounded-corners.html
compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html
compositing/layer-creation/fixed-position-out-of-view-scaled.html
Comment 125 WebKit Review Bot 2013-02-09 13:42:01 PST
Comment on attachment 187420 [details]
Avoided assert and rebaselined platform/chromium

Attachment 187420 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/16467597

New failing tests:
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view-scaled.html
platform/chromium/compositing/rounded-corners.html
compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html
compositing/layer-creation/fixed-position-out-of-view-scaled.html
Comment 126 Alok Priyadarshi 2013-02-20 10:32:59 PST
Created attachment 189336 [details]
Updated mac baselines
Comment 127 WebKit Review Bot 2013-02-20 11:34:05 PST
Comment on attachment 189336 [details]
Updated mac baselines

Attachment 189336 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/16651456

New failing tests:
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html
platform/chromium/virtual/softwarecompositing/layer-creation/fixed-position-out-of-view-scaled.html
compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html
compositing/layer-creation/fixed-position-out-of-view-scaled.html
Comment 128 Build Bot 2013-02-20 17:45:18 PST
Comment on attachment 189336 [details]
Updated mac baselines

Attachment 189336 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://queues.webkit.org/results/16650662

New failing tests:
compositing/contents-opaque/contents-opaque-layer-transform.html
compositing/rtl/rtl-fixed.html
compositing/rtl/rtl-fixed-overflow.html
compositing/contents-opaque/contents-opaque-background-color.html
compositing/contents-opaque/contents-opaque-layer-opacity.html
Comment 129 Alok Priyadarshi 2013-02-21 10:27:22 PST
Committed r143626: <http://trac.webkit.org/changeset/143626>
Comment 130 Simon Fraser (smfr) 2013-03-07 17:52:22 PST
This causes garbage to show up in tiles at http://chainlove.com on Mac.
Comment 131 Simon Fraser (smfr) 2013-03-11 11:18:26 PDT
(In reply to comment #130)
> This causes garbage to show up in tiles at http://chainlove.com on Mac.

I filed bug 112043 to cover this.
Comment 132 Simon Fraser (smfr) 2013-03-11 11:50:54 PDT
I'm going to roll this out. It's too hard to fix easily.

What this needs to do is to take account of paint phases all the way from GraphicsLayers down to RenderObjects. The code needs to mirror the painting code.
Comment 133 Simon Fraser (smfr) 2013-03-11 11:53:45 PDT
Ugh, the rollout is hard with all the test changes.

Alok, please take care of this.
Comment 134 Alok Priyadarshi 2013-03-11 12:26:00 PDT
(In reply to comment #133)
> Ugh, the rollout is hard with all the test changes.
> 
> Alok, please take care of this.

Yes rollout will be really painful. I do not see why it needs to mirror the paint code. Can you provide a simple test case? Also why is it mac only? I cannot reproduce it on chromium windows and linux. I still need to check chromium mac.
Comment 135 James Robinson 2013-03-11 12:28:07 PDT
(In reply to comment #134)
> (In reply to comment #133)
> > Ugh, the rollout is hard with all the test changes.
> > 
> > Alok, please take care of this.
> 
> Yes rollout will be really painful. I do not see why it needs to mirror the paint code. Can you provide a simple test case? Also why is it mac only? I cannot reproduce it on chromium windows and linux. I still need to check chromium mac.

(In reply to comment #134)
> (In reply to comment #133)
> > Ugh, the rollout is hard with all the test changes.
> > 
> > Alok, please take care of this.
> 
> Yes rollout will be really painful. I do not see why it needs to mirror the paint code. Can you provide a simple test case? Also why is it mac only? I cannot reproduce it on chromium windows and linux. I still need to check chromium mac.

Alok, let's figure that out with the patch rolled out.  There are a number of bugs chromium-side as well about this change.
Comment 136 Simon Fraser (smfr) 2013-03-11 12:48:15 PDT
On chainlove.com there's a negative z-index child behind the main content, which makes the body compositing layer get an m_foregroundLayer. This means that the m_graphicsLayer doesn't paint everything, but we've told it that it's opaque, so we get garbage. This is most apparent if you load the page with JS disabled.

You need to take paint phases in to account because you have to be able to answer the "is opaque" question for each GraphicsLayer, and different GraphicsLayers paint different phases.
Comment 137 Alok Priyadarshi 2013-03-11 12:52:50 PDT
Trying rollout.
Comment 138 Alok Priyadarshi 2013-03-13 22:38:26 PDT
Created attachment 193067 [details]
simplified chainlove.com

I created a simplified version of chainlove.com to understand the problem. The issue here is very simple. The body-element layer is getting composited due to various CSS settings. The body layer is getting marked as opaque because it has an explicit background. And we optimize out painting of the body background.

See RenderBox::paintBackground.
http://trac.webkit.org/browser/trunk/Source/WebCore/rendering/RenderBox.cpp#L1127

If we always paint the body background, everything paints perfectly. There are two ways to fix the problem:
1. Do not mark the body-element layer as opaque. This seems like a band-aid.
2. Fix the optimization in RenderBox::paintBackground. It assumes that body will either never be composited or always drawn with blending enabled.

Also see crbug.com/181015 which has a even simpler example.
Comment 139 Simon Fraser (smfr) 2013-03-14 09:21:41 PDT
(In reply to comment #138)
> Created an attachment (id=193067) [details]
> simplified chainlove.com
> 
> I created a simplified version of chainlove.com to understand the problem. The issue here is very simple. The body-element layer is getting composited due to various CSS settings. The body layer is getting marked as opaque because it has an explicit background. And we optimize out painting of the body background.
> 
> See RenderBox::paintBackground.
> http://trac.webkit.org/browser/trunk/Source/WebCore/rendering/RenderBox.cpp#L1127
> 
> If we always paint the body background, everything paints perfectly. There are two ways to fix the problem:
> 1. Do not mark the body-element layer as opaque. This seems like a band-aid.
> 2. Fix the optimization in RenderBox::paintBackground. It assumes that body will either never be composited or always drawn with blending enabled.
> 
> Also see crbug.com/181015 which has a even simpler example.

I think you're missing the fact that a single RenderLayer can be painted by multiple GraphicsLayers, with each GL painting a different phase. On chainlove.com, an element with negative z-index is causing the body layer to get "background" and "foreground" GraphicsLayer, so your opaqueness logic has to compute opaqueness separately for each phase, in order to mark those two layers opaque correctly.
Comment 140 Alok Priyadarshi 2013-03-14 12:52:22 PDT
Created attachment 193174 [details]
Patch
Comment 141 Alok Priyadarshi 2013-03-14 12:53:34 PDT
Actually on chainlove.com. I see the body layer getting only the foreground GraphicsLayer, not the background. The main issue was <body>'s background not getting painted.

Anyways you are right about the need to compute opaqueness separately given that different GraphicsLayers paint different phases. The new patch fixes these issues. The patch still needs tests and a proper ChangeLog. PTAL.
Comment 142 WebKit Review Bot 2013-03-14 14:05:36 PDT
Comment on attachment 193174 [details]
Patch

Attachment 193174 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://webkit-commit-queue.appspot.com/results/17209111

New failing tests:
compositing/geometry/bounds-ignores-hidden.html
compositing/geometry/clip.html
compositing/geometry/limit-layer-bounds-positioned.html
compositing/absolute-inside-out-of-view-fixed.html
compositing/geometry/limit-layer-bounds-clipping-ancestor.html
http/tests/cache/subresource-failover-to-network.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/iframes/become-overlapped-iframe.html
compositing/filters/sw-shadow-overlaps-hw-layer.html
compositing/geometry/layer-due-to-layer-children-switch.html
compositing/geometry/preserve-3d-switching.html
compositing/geometry/bounds-ignores-hidden-composited-descendant.html
compositing/geometry/limit-layer-bounds-overflow-root.html
compositing/filters/sw-layer-overlaps-hw-shadow.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
compositing/geometry/clip-inside.html
compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
compositing/columns/composited-in-paginated.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/bounds-ignores-hidden-dynamic.html
compositing/geometry/limit-layer-bounds-transformed.html
compositing/clip-child-by-non-stacking-ancestor.html
compositing/geometry/flipped-writing-mode.html
compositing/overflow-trumps-transform-style.html
compositing/backing/no-backing-for-clip.html
compositing/backing/no-backing-for-clip-overlap.html
compositing/backing/no-backing-for-perspective.html
Comment 143 WebKit Review Bot 2013-03-14 14:32:14 PDT
Comment on attachment 193174 [details]
Patch

Attachment 193174 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://webkit-commit-queue.appspot.com/results/17136285

New failing tests:
compositing/geometry/bounds-ignores-hidden.html
compositing/geometry/clip.html
compositing/geometry/limit-layer-bounds-positioned.html
compositing/absolute-inside-out-of-view-fixed.html
compositing/geometry/limit-layer-bounds-clipping-ancestor.html
http/tests/cache/subresource-failover-to-network.html
compositing/geometry/fixed-position-composited-switch.html
compositing/geometry/limit-layer-bounds-transformed-overflow.html
compositing/iframes/become-overlapped-iframe.html
compositing/filters/sw-shadow-overlaps-hw-layer.html
compositing/geometry/layer-due-to-layer-children-switch.html
compositing/geometry/preserve-3d-switching.html
compositing/geometry/bounds-ignores-hidden-composited-descendant.html
compositing/geometry/limit-layer-bounds-overflow-root.html
compositing/filters/sw-layer-overlaps-hw-shadow.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
compositing/geometry/clip-inside.html
compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
compositing/columns/composited-in-paginated.html
compositing/iframes/become-composited-nested-iframes.html
compositing/geometry/bounds-ignores-hidden-dynamic.html
compositing/geometry/limit-layer-bounds-transformed.html
compositing/clip-child-by-non-stacking-ancestor.html
compositing/geometry/flipped-writing-mode.html
compositing/overflow-trumps-transform-style.html
compositing/backing/no-backing-for-clip.html
compositing/backing/no-backing-for-clip-overlap.html
compositing/backing/no-backing-for-perspective.html
Comment 144 Simon Fraser (smfr) 2013-03-14 16:11:18 PDT
Comment on attachment 193174 [details]
Patch

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

> Source/WebCore/rendering/RenderBox.cpp:1134
> +        if (documentElementRenderer && !documentElementRenderer->hasBackground() && documentElementRenderer == parent() && !isComposited)
>              return;

This is wrong. The change is causing the body background to be rendered twice sometimes (once into the page layer, once into the body layer), and you're only doing this to work around deficiencies in the "is opaque" logic.
Comment 145 Alok Priyadarshi 2013-03-14 16:32:01 PDT
Comment on attachment 193174 [details]
Patch

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

>> Source/WebCore/rendering/RenderBox.cpp:1134
>>              return;
> 
> This is wrong. The change is causing the body background to be rendered twice sometimes (once into the page layer, once into the body layer), and you're only doing this to work around deficiencies in the "is opaque" logic.

What is the deficiency in "is opaque" logic? The primary/background GraphicsLayer for the <body> layer is being marked opaque because it IS opaque.

I would argue that this optimization is wrong. It assumes that either <body> will never be composited or always blended. Yes there is redundant painting but that redundancy should be optimized at the page layer level, not the body layer. Page layer is the one that is occluded.

BTW in case it is not clear, redundant painting will happen only when the body layer is composited, not always. Not sure how common this case is.
Comment 146 Simon Fraser (smfr) 2013-03-14 17:09:17 PDT
(In reply to comment #145)
> (From update of attachment 193174 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=193174&action=review
> 
> >> Source/WebCore/rendering/RenderBox.cpp:1134
> >>              return;
> > 
> > This is wrong. The change is causing the body background to be rendered twice sometimes (once into the page layer, once into the body layer), and you're only doing this to work around deficiencies in the "is opaque" logic.
> 
> What is the deficiency in "is opaque" logic? The primary/background GraphicsLayer for the <body> layer is being marked opaque because it IS opaque.

As I keep saying, the "is opaque" logic needs to know about paint phases.

The fact that this patch touches painting code shows that it's wrong.
Comment 147 Alok Priyadarshi 2013-03-15 10:42:18 PDT
> As I keep saying, the "is opaque" logic needs to know about paint phases.
> 
> The fact that this patch touches painting code shows that it's wrong.

I still do not understand why it needs to know about paint phases when "is opaque" logic is making a decision based on just the background and marking the layer that paints background as opaque/not.

The logic seems fine except for the composited body element that does not paint the background under certain conditions. I thought that composited <body> element not painting background is wrong, but I was told that this weirdness is expected according to the CSS spec. This particular issue can be fixed independent of this bug and I have opened a separate bug:
https://bugs.webkit.org/show_bug.cgi?id=112454

Once the other bug is fixed, I would not need to touch any paint code or handle the body element specially here.
Comment 148 Simon Fraser (smfr) 2013-03-15 11:04:45 PDT
Comment on attachment 193174 [details]
Patch

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

> Source/WebCore/rendering/RenderLayerBacking.cpp:701
> +    if (!m_isMainFrameRenderViewLayer) {
> +        bool backgroundIsOpaque = m_owningLayer->backgroundIsKnownToBeOpaqueInRect(localCompositingBounds);
> +        GraphicsLayer* backgroundPaintingLayer = m_backgroundLayer ? m_backgroundLayer.get() : m_graphicsLayer.get();
> +        backgroundPaintingLayer->setContentsOpaque(backgroundIsOpaque);

Currently m_isMainFrameRenderViewLayer is the only layer that will have a m_backgroundLayer, so this logic isn't really needed.
Comment 149 Simon Fraser (smfr) 2013-03-15 11:07:53 PDT
(In reply to comment #147)
> > As I keep saying, the "is opaque" logic needs to know about paint phases.
> > 
> > The fact that this patch touches painting code shows that it's wrong.
> 
> I still do not understand why it needs to know about paint phases when "is opaque" logic is making a decision based on just the background and marking the layer that paints background as opaque/not.
> 
> The logic seems fine except for the composited body element that does not paint the background under certain conditions. I thought that composited <body> element not painting background is wrong, but I was told that this weirdness is expected according to the CSS spec. This particular issue can be fixed independent of this bug and I have opened a separate bug:
> https://bugs.webkit.org/show_bug.cgi?id=112454
> 
> Once the other bug is fixed, I would not need to touch any paint code or handle the body element specially here.

I think you are correct. Your Changelog should make it clear that this is just a first step that only considers the primary graphics layer, and only looks at backgrounds. Ideally we'd be able to set other layers as being opaque if we had enough knowledge of their contents, and at that point we would have to consider paint phases.
Comment 150 Alok Priyadarshi 2013-03-19 12:18:35 PDT
Created attachment 193895 [details]
Patch
Comment 151 Alok Priyadarshi 2013-03-19 12:22:15 PDT
I decided to fix bug 112454 here itself because it was much easier to test. Notice two new test cases in the new patch - body-background-skipped and body-background-painted. Rest of the test cases are the same as original patch.

Most of the code is also from the original patch except for the case handled by skipBodyBackground().
Comment 152 WebKit Review Bot 2013-03-19 13:10:07 PDT
Comment on attachment 193895 [details]
Patch

Attachment 193895 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://webkit-commit-queue.appspot.com/results/17212516

New failing tests:
compositing/geometry/bounds-ignores-hidden.html
compositing/geometry/clip.html
compositing/contents-opaque/body-background-painted.html
compositing/geometry/limit-layer-bounds-positioned.html
compositing/geometry/bounds-ignores-hidden-composited-descendant.html
compositing/geometry/limit-layer-bounds-clipping-ancestor.html
http/tests/cache/subresource-failover-to-network.html
compositing/contents-opaque/background-color.html
compositing/geometry/fixed-position-composited-switch.html
compositing/contents-opaque/layer-transform.html
compositing/filters/sw-shadow-overlaps-hw-layer.html
compositing/geometry/layer-due-to-layer-children-switch.html
compositing/absolute-inside-out-of-view-fixed.html
compositing/geometry/limit-layer-bounds-overflow-root.html
compositing/filters/sw-layer-overlaps-hw-shadow.html
compositing/geometry/limit-layer-bounds-fixed-positioned.html
compositing/geometry/layer-due-to-layer-children-deep-switch.html
compositing/geometry/limit-layer-bounds-positioned-transition.html
compositing/geometry/clip-inside.html
compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html
compositing/columns/composited-in-paginated.html
compositing/geometry/bounds-ignores-hidden-dynamic.html
compositing/contents-opaque/layer-opacity.html
compositing/contents-opaque/body-background-skipped.html
compositing/clip-child-by-non-stacking-ancestor.html
compositing/geometry/flipped-writing-mode.html
compositing/overflow-trumps-transform-style.html
compositing/backing/no-backing-for-clip.html
compositing/backing/no-backing-for-clip-overlap.html
compositing/backing/no-backing-for-perspective.html
Comment 153 Alok Priyadarshi 2013-03-20 14:51:34 PDT
smfr: Could you please review. I will rebaseline all the failing tests before landing.
Comment 154 Simon Fraser (smfr) 2013-03-20 15:22:01 PDT
Comment on attachment 193895 [details]
Patch

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

> Source/WebCore/rendering/RenderBox.cpp:95
> +static bool skipBodyBackground(const RenderBox* bodyElementRenderer)

This function name is unclear. Skip for what?

> Source/WebCore/rendering/RenderLayer.cpp:5539
> +    // It is somehow getting triggered during style update.

The "somehow" is a bit mysterious. You should investigate and file a bug.
Comment 155 Alok Priyadarshi 2013-03-21 00:29:36 PDT
Comment on attachment 193895 [details]
Patch

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

>> Source/WebCore/rendering/RenderBox.cpp:95
>> +static bool skipBodyBackground(const RenderBox* bodyElementRenderer)
> 
> This function name is unclear. Skip for what?

Would skipsPaintingBodyBackground be better? I was following the same convention as skipRootBackground.

>> Source/WebCore/rendering/RenderLayer.cpp:5539
>> +    // It is somehow getting triggered during style update.
> 
> The "somehow" is a bit mysterious. You should investigate and file a bug.

Will do.
Comment 156 Alok Priyadarshi 2013-03-21 15:32:27 PDT
Committed r146531: <http://trac.webkit.org/changeset/146531>
Comment 157 Simon Fraser (smfr) 2013-04-18 13:17:12 PDT
This caused bug 114825.
Comment 158 Jer Noble 2013-04-25 18:07:54 PDT
This also cause bug #115216.