Bug 58834 - [chromium] Draw the root/"non-composited content" in compositor side
Summary: [chromium] Draw the root/"non-composited content" in compositor side
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: 528+ (Nightly build)
Hardware: PC OS X 10.5
: P2 Normal
Assignee: Nat Duca
URL:
Keywords:
Depends on: 66497
Blocks: 58799 66065
  Show dependency treegraph
 
Reported: 2011-04-18 14:53 PDT by James Robinson
Modified: 2011-08-18 15:43 PDT (History)
8 users (show)

See Also:


Attachments
work in progress, scrolling and offscreen compositing don't work (30.73 KB, patch)
2011-07-28 19:43 PDT, James Robinson
no flags Details | Formatted Diff | Diff
Patch (39.39 KB, patch)
2011-08-11 20:12 PDT, James Robinson
no flags Details | Formatted Diff | Diff
Patch (54.62 KB, patch)
2011-08-15 20:16 PDT, James Robinson
no flags Details | Formatted Diff | Diff
Patch (1.10 MB, patch)
2011-08-16 15:55 PDT, James Robinson
no flags Details | Formatted Diff | Diff
Patch (1.10 MB, patch)
2011-08-16 16:09 PDT, James Robinson
no flags Details | Formatted Diff | Diff
Patch (1.10 MB, patch)
2011-08-17 12:35 PDT, James Robinson
no flags Details | Formatted Diff | Diff
get rid of ???s in GraphicsLayerClient implementations (1.10 MB, patch)
2011-08-17 13:45 PDT, James Robinson
no flags Details | Formatted Diff | Diff
now with less blue on windows (933.84 KB, patch)
2011-08-18 15:05 PDT, James Robinson
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description James Robinson 2011-04-18 14:53:23 PDT
Currently the root content (what the WK2 compositor calls the non-composited content) is special-cased by LayerRendererChromium and rendered differently from how *LayerChromium or CCLayerImpls are rendered.  We need to somehow render this from the compositor side.

I currently think that the easiest way to do this will be to create a CCLayerImpl of the appropriate type (probably the same type as ContentLayerChromiums have) and during the tree syncing phase set it up at the appropriate point.  From the compositor thread side the "root layer" content can be treated the same way as any other layer, IMO.  This will be clearer when the other issues blocking bug 58799 are resolved.
Comment 1 James Robinson 2011-07-28 19:43:21 PDT
Created attachment 102327 [details]
work in progress, scrolling and offscreen compositing don't work
Comment 2 Adrienne Walker 2011-07-29 16:55:34 PDT
Is it too complicated (or too at odds with WK2) to make a graphics layer for the non-composited content and stick that in the graphics layer tree? It just seems like it shouldn't be special on either end.
Comment 3 James Robinson 2011-08-01 16:22:00 PDT
(In reply to comment #2)
> Is it too complicated (or too at odds with WK2) to make a graphics layer for the non-composited content and stick that in the graphics layer tree? It just seems like it shouldn't be special on either end.

That's what this does - NonCompositedContentHost has a GraphicsLayer that is stuck into the tree at the appropriate place. NonCompositedContentHost is that layer's GraphicsLayerClient so it can route paint calls out through the appropriate paint interface.
Comment 4 Adrienne Walker 2011-08-01 16:28:29 PDT
(In reply to comment #3)
> (In reply to comment #2)
> > Is it too complicated (or too at odds with WK2) to make a graphics layer for the non-composited content and stick that in the graphics layer tree? It just seems like it shouldn't be special on either end.
> 
> That's what this does - NonCompositedContentHost has a GraphicsLayer that is stuck into the tree at the appropriate place. NonCompositedContentHost is that layer's GraphicsLayerClient so it can route paint calls out through the appropriate paint interface.

I think I had a misunderstanding and thought this would be simpler on the main thread side.  Sorry for my confusion.

This does nicely clean up a lot of LayerRendererChromium.  :)
Comment 5 James Robinson 2011-08-11 20:12:22 PDT
Created attachment 103728 [details]
Patch
Comment 6 James Robinson 2011-08-11 20:16:06 PDT
Scrolling still doesn't work.  I'm not sure why - as far as I can tell, scrolling a layer is just changing the relationship between layer space and content space.  I'm calling LayerTilerChromium::setLayerPosition(-scrollPosition()) at what I think is the appropriate time, but no dice.  It sort of works when testing manually until I scroll too far then it all goes to hell.

Looking at the code I don't think we've ever called LayerTilerChromium::setLayerPosition(), so maybe that just doesn't work?  Not sure.
Comment 7 Adrienne Walker 2011-08-11 20:32:30 PDT
(In reply to comment #6)
> Scrolling still doesn't work.  I'm not sure why - as far as I can tell, scrolling a layer is just changing the relationship between layer space and content space.  I'm calling LayerTilerChromium::setLayerPosition(-scrollPosition()) at what I think is the appropriate time, but no dice.  It sort of works when testing manually until I scroll too far then it all goes to hell.
> 
> Looking at the code I don't think we've ever called LayerTilerChromium::setLayerPosition(), so maybe that just doesn't work?  Not sure.

setLayerPosition used to be called for scrollbars.  I'm going to change it to setLayerTransform for RTL layers, so I haven't removed it yet.

I'm pretty sure setLayerPosition affects both paint and draw.  If you look at the code you're changing, the scroll is only passed during the draw step.  The root layer here is unfortunately special.  Maybe you could take the scroll out during the WebViewImplContentPainter step so that we can be consistent?
Comment 8 Adrienne Walker 2011-08-11 20:33:48 PDT
(In reply to comment #7)

> setLayerPosition used to be called for scrollbars.  I'm going to change it to setLayerTransform for RTL layers, so I haven't removed it yet.

Also, given that nothing currently uses it, it's likely that it doesn't work.  I'm pretty sure there's at least one place in the AA code where (what the tiler calls) layer space and content space are confused.
Comment 9 James Robinson 2011-08-15 20:16:31 PDT
Created attachment 103997 [details]
Patch
Comment 10 James Robinson 2011-08-15 20:22:51 PDT
All compositing layout tests pass on this version except for 
compositing/reflections/nested-reflection-mask-change.html (lawl), where the mask isn't being applied.  I'll look into that tomorrow.

The scroll offset itself is used:
- to manipulate the draw transform by modifying TiledLayerChromium::tilingTransform
- at paint time by moving visibleLayerRect in paintLayerContents()

does that sound like it should be sufficient? It seems to work.

I also added a bit on layers indicating whether they should get the root layer special treatment, which currently means forcing subpixel text rendering to on (which does not have any impact on DumpRenderTree, since subpixel is always off for all text in DRT) and masking the alpha channel at draw time which according to comments is necessary on windows.

I also had to remove a clip in ContentLayerChromium::paintContentsIfDirty, because otherwise it was throwing away all invalidations outside the content's initial viewable bounds.  I could move this rect by the scroll offset but looking at the code it seems wrong to disregard dirties outside the bounds.  Given that the current code seems to work correctly there must be something I'm missing here :).  Otherwise this is all shuffling things about.
Comment 11 James Robinson 2011-08-15 20:23:35 PDT
Oh, and a few tests have some very small rendering differences that I can't fully explain.  A lot of these are the corners of scrollbars, which makes me hope that I've somehow magically fixed the debug/release linux scrollbar rendering differences.  I haven't confirmed that yet.
Comment 12 Adrienne Walker 2011-08-16 10:58:03 PDT
Comment on attachment 103997 [details]
Patch

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

> Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp:-106
> -    dirty.intersect(IntRect(IntPoint(), contentBounds()));

I still don't understand why this line needs to be cut.  Does that mean that invalidations might also need to be adjusted by the scroll offset?

I added this line in the past because sometimes invalidations were outside the bounds of the layer's contents.  Because the tiler has no explicit resize (which is probably a mistake), it just grows to incorporate the size of the invalidations passed to it.  This was causing layers to actually become larger than they should be and drawing incorrectly.

> Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h:63
> +    virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, bool isRootLayer) = 0;

Nit: "isRootLayer" seems weird to pass into prepareToUpdate as a function argument.  Subpixel AA seems more like a property on the tiler, like border texels.  And also one that, when changed, should reset the tiler.  I realize that the root layer won't change, but in the future we might want to speculatively enable subpixel AA on more layers if we know they're opaque and their screen space transforms are kosher.  I suppose I could also just change that later when adding that functionality too.
Comment 13 James Robinson 2011-08-16 15:55:33 PDT
Created attachment 104110 [details]
Patch
Comment 14 James Robinson 2011-08-16 16:09:11 PDT
Created attachment 104113 [details]
Patch
Comment 15 James Robinson 2011-08-16 16:44:31 PDT
This patch works fine as far I can tell - the compositing/ layout tests pass and manual testing things seem to work fine (scrolling works, the expected things have subpixel AA, subframe scrolling works, etc).

One bit that I'm really unsure about is the change to the dirty rect clipping in ContentLayerChromium::paintContentsIfDirty().  Previously the code clipped m_dirtyRect to the rect ((0, 0), contentBounds()), which makes sense.  I had to change that to (scrollPosition(), contentBounds()) or there was a lot of blue whenever the root layer was scrolled slightly.  This showed up in several layout tests that scroll (most that test fixed positioning) and in manual testing.  This feels wrong because I think that contentBounds() should cover the entire content bounds of the layer, not just the currently visible portion.  Do you happen to know what is going on, Adrienne?  Given that this patch works and this area seems pretty well tested I'm OK with landing this, but it seems like something somewhere is confused (possibly just me).
Comment 16 James Robinson 2011-08-16 19:02:44 PDT
Aha, the issue was that the non composited content's layer size was set to the viewport size, not the contents size.  With that fixed the original clipping logic works correctly.  I think we're good to go now!
Comment 17 Adrienne Walker 2011-08-17 11:58:12 PDT
Comment on attachment 104113 [details]
Patch

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

> Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp:252
> -void LayerTilerChromium::prepareToUpdate(const IntRect& contentRect, LayerTextureUpdater* textureUpdater)
> +void LayerTilerChromium::prepareToUpdate(const IntRect& layerRect, LayerTextureUpdater* textureUpdater)

Nit: can you also remove this transformation? I think this is a terminology mismatch.  contentRect (in the tiler sense) is right here and there's no need to also have the line in this function to transform from layer to content space.  I should just rename everything in the tiler from content space => layer space and layer space => tile space.
Comment 18 James Robinson 2011-08-17 12:16:18 PDT
(In reply to comment #17)
> (From update of attachment 104113 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=104113&action=review
> 
> > Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp:252
> > -void LayerTilerChromium::prepareToUpdate(const IntRect& contentRect, LayerTextureUpdater* textureUpdater)
> > +void LayerTilerChromium::prepareToUpdate(const IntRect& layerRect, LayerTextureUpdater* textureUpdater)
> 
> Nit: can you also remove this transformation? I think this is a terminology mismatch.  contentRect (in the tiler sense) is right here and there's no need to also have the line in this function to transform from layer to content space.  I should just rename everything in the tiler from content space => layer space and layer space => tile space.

Definitely, I'll revert this back.  I made this change when I was more confused about content vs layer space in LayerTilerChromium.
Comment 19 James Robinson 2011-08-17 12:35:18 PDT
Created attachment 104215 [details]
Patch
Comment 20 Adrienne Walker 2011-08-17 13:13:18 PDT
Comment on attachment 104215 [details]
Patch

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

In general, this looks good to me.  I have just one small question and a nit.

The scrollbars changing is really unexpected to me.  Is this your local DRT output, or are the scrollbars really changing on the bots as well?

> Source/WebCore/platform/graphics/chromium/NonCompositedContentHost.cpp:74
> +    // ???

Nit: I think it'd be better to sort out if anything is needed here and leave more informative comments.
Comment 21 James Robinson 2011-08-17 13:18:29 PDT
I don't know how to explain the scrollbar diffs, but they are reliably rendering differently on my box with this patch compared to without. http://knowyourmeme.com/i/3308/original/xjobz5hofa.jpg?1244616067
Comment 22 James Robinson 2011-08-17 13:45:46 PDT
Created attachment 104228 [details]
get rid of ???s in GraphicsLayerClient implementations
Comment 23 Adrienne Walker 2011-08-17 14:16:03 PDT
Unofficially, LGTM.
Comment 24 James Robinson 2011-08-18 10:45:40 PDT
Can I get an official review for this, please?
Comment 25 WebKit Review Bot 2011-08-18 12:07:33 PDT
Comment on attachment 104228 [details]
get rid of ???s in GraphicsLayerClient implementations

Clearing flags on attachment: 104228

Committed r93329: <http://trac.webkit.org/changeset/93329>
Comment 26 WebKit Review Bot 2011-08-18 12:07:47 PDT
All reviewed patches have been landed.  Closing bug.
Comment 27 James Robinson 2011-08-18 15:05:39 PDT
Created attachment 104405 [details]
now with less blue on windows
Comment 28 James Robinson 2011-08-18 15:11:23 PDT
Patch updated to disable blending when drawing the root layer.  This is necessary on windows because GDI puts garbage in the alpha channel, so in the previous version of the patch all the text on the root layer was ending up blue (from the fullscreen clear to blue at the start of the composite).

There are still some weird scrollbar diffs, but with this patch for some reason most of the release vs debug differences go away (everything except for compositing/geometry/horizontal-scroll-composited.html).  I still don't fully grok this but it makes me happy!
Comment 29 James Robinson 2011-08-18 15:11:55 PDT
Here's the code diff to the previous version:


diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index 9044997..a7e232c 100644
--- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -751,9 +751,6 @@ void LayerRendererChromium::drawLayersInternal()
     GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST));
     GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE));
 
-    // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType.
-    GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
-
     useRenderSurface(m_defaultRenderSurface);
 
     // Clear to blue to make it easier to spot unrendered regions.
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp
index 637209b..d217e94 100644
--- a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp
+++ b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp
@@ -53,14 +53,18 @@ void CCTiledLayerImpl::draw()
     const IntRect& layerRect = visibleLayerRect();
     if (!layerRect.isEmpty()) {
         GraphicsContext3D* context = layerRenderer()->context();
-        // Mask out writes to the alpha channel for the root layer, subpixel antialiasing
-        // via Skia results in invalid zero alpha values on text glyphs. The root layer
-        // is always opaque so the alpha channel isn't meaningful anyway.
-        if (isRootLayer())
-            context->colorMask(true, true, true, false);
+        // Mask out writes to the alpha channel and disable blending for the root layer,
+        // subpixel antialiasing on windows results in invalid zero alpha values on text
+        // glyphs. The root layer is always opaque so the alpha channel isn't meaningful anyway.
+        if (isRootLayer()) {
+            GLC(context, context->colorMask(true, true, true, false));
+            GLC(context, context->disable(GraphicsContext3D::BLEND));
+        }
         m_tiler->draw(layerRect, m_tilingTransform, drawOpacity());
-        if (isRootLayer())
+        if (isRootLayer()) {
             context->colorMask(true, true, true, true);
+            GLC(context, context->enable(GraphicsContext3D::BLEND));
+        }
     }
 }
Comment 30 Adrienne Walker 2011-08-18 15:18:33 PDT
Those code changes look good to me, so long as the tests are passing now.

I still don't fully understand the minor scrollbar issues either, but not having debug vs. release issues seems like a positive change.
Comment 31 Kenneth Russell 2011-08-18 15:24:41 PDT
Comment on attachment 104405 [details]
now with less blue on windows

r=me based on enne's unofficial review.
Comment 32 James Robinson 2011-08-18 15:25:54 PDT
Thanks, Ken!
Comment 33 WebKit Review Bot 2011-08-18 15:42:55 PDT
Comment on attachment 104405 [details]
now with less blue on windows

Clearing flags on attachment: 104405

Committed r93360: <http://trac.webkit.org/changeset/93360>
Comment 34 WebKit Review Bot 2011-08-18 15:43:11 PDT
All reviewed patches have been landed.  Closing bug.