Bug 90419 - When overlap testing, compute regions relative to some container, not absolute
Summary: When overlap testing, compute regions relative to some container, not absolute
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-07-02 18:12 PDT by Simon Fraser (smfr)
Modified: 2022-09-20 06:11 PDT (History)
9 users (show)

See Also:


Attachments
Testcase (1.08 KB, text/html)
2012-07-05 14:01 PDT, Simon Fraser (smfr)
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Simon Fraser (smfr) 2012-07-02 18:12:07 PDT
Currently the overlap testing code computes all layer bounds in absolute coords, and adds them to regions in the overlap map's region stack.

This doesn't make too much sense when elements are 3d-transformed (e.e. by flips), and can be very expensive.

I think it would be better to treat certain layers as "overlap-test containers", and when traversing descendants, to compute regions relative to those containers. E.g. 3d-transformed element would be containers. When you pop that layer off the stack, you could map its region bounds into the space of the parent container.
Comment 1 Simon Fraser (smfr) 2012-07-03 18:27:49 PDT
This code in RenderLayer::calculateClipRects() seems just wrong:

        // This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across
        // some transformed layer boundary, for example, in the RenderLayerCompositor overlapMap, where
        // clipRects are needed in view space.
        LayoutPoint offset;
        offset = roundedIntPoint(renderer()->localToContainerPoint(FloatPoint(), rootLayer->renderer()));
        RenderView* view = renderer()->view();
        ASSERT(view);
        if (view && clipRects.fixed() && rootLayer->renderer() == view) {
            offset -= view->frameView()->scrollOffsetForFixedPosition();
        }

You can't just offset when mapping rects through transforms.

It really doesn't make any sense to ask for global clip rects when there are transforms. That's why transforms are normally act as clipping roots.

This is causing some issues in content we have that does rotateY(180deg); the overlap testing is just broken.
Comment 2 Simon Fraser (smfr) 2012-07-05 14:01:18 PDT
Created attachment 150981 [details]
Testcase
Comment 3 Simon Fraser (smfr) 2012-07-06 13:01:18 PDT
This is a bit harder than I thought. I think we should treat layers with transforms as overlap region roots, but we may not be pushing a transformed layer onto the OverlapMap at first; we won't until we discover that it has composited descendants.
Comment 4 Simon Fraser (smfr) 2012-07-06 16:39:18 PDT
Another wrinkle; accumulating into the  m_overlapStack[m_overlapStack.size() - 2] region is problematic because that may cross a transform boundary.
Comment 5 Simon Fraser (smfr) 2012-07-07 11:48:28 PDT
For some reason I'm finding it really hard to fix this. The OverlapMap messes with my brain.

As well as mapping regions in the overlap map up through transforms, we need to also clip them. I think this is very similar to what RenderObject::computeRectForRepaint() does, but that is designed to be called during layout.
Comment 6 Simon Fraser (smfr) 2012-07-19 14:51:13 PDT
We should also consider elements with animating transofrms as "islands" of overlap testing. Bug 91787.
Comment 7 Max Shishkin 2013-01-19 12:08:09 PST
I ran onto similar issue when rotated element overlaps another element, which is on top of it.

In Chrome the top element seems to be correctly placed (no overlap is visible), but once you try to hover it - after a certain point the hover is not working anymore.

In Safari and in the latest nighty build of standalone Webkit (r140252 at the time of writing) - you actually can see that the bottom square overlaps the top at some point.

Demo - http://codepen.io/angryObject/full/rcdHm.
Comment 8 Shawn Singh 2013-01-22 15:23:46 PST
(In reply to comment #7)
> I ran onto similar issue when rotated element overlaps another element, which is on top of it.
> 
> In Chrome the top element seems to be correctly placed (no overlap is visible), but once you try to hover it - after a certain point the hover is not working anymore.
> 
> In Safari and in the latest nighty build of standalone Webkit (r140252 at the time of writing) - you actually can see that the bottom square overlaps the top at some point.
> 
> Demo - http://codepen.io/angryObject/full/rcdHm.

Unless I misunderstood your comments - what you're seeing on that link is a different meaning of "overlap" related to hit-testing / layer sorting / preserve-3d.  Chrome and Safari may not have matching semantics (yet) about preserve-3d (or lack thereof in your example), due to different layer sorting implementation quirks.

The overlap Simon is referring to is an implementation detail when choosing what parts of the DOM can be grouped together into an accelerated composited layer; sometimes layers need to be forced to become compositing because they overlap other things that are compositing, so that we can keep the desired paint-order as per CSS 2.1 spec.
Comment 9 Ahmad Saleem 2022-09-20 06:11:40 PDT
From the attached, I do see "red" in all browsers (Safari 16, Firefox Nightly 107 and Chrome Canary 108) but the red area in Safari 16 is more than all other browsers (half while 1/4 in others).