Bug 266478 - Background image of the body element not rendered in some situations
Summary: Background image of the body element not rendered in some situations
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: Compositing (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: BrowserCompat, InRadar
Depends on:
Blocks:
 
Reported: 2023-12-15 07:14 PST by Miguel Gomez
Modified: 2024-04-05 07:04 PDT (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Miguel Gomez 2023-12-15 07:14:09 PST
The problem can be reproduced with this test page https://people.igalia.com/magomez/bodybackground/bad.html

The body element has a background image (in this case it's just a blue rectangle). The usage of negative z-index values in some of the layers causes that this image is not rendered. The elements rendered in the body layer are rendered (the green rectangle that's shown is rendered into that layer). And if the background-image is replaced with a background-color, the background color is rendered properly.

This reproduces on recent gtk, wpe and mac versions.
Comment 1 Miguel Gomez 2023-12-15 07:27:50 PST
Curious fact that may be helpful: when testing this on safari, clicking on the button on the top right corner of the window that shows all the tabs (or apps, not sure), the background image gets shown while on that summary state. Exiting that and going back to the window makes the background image disappear.
Comment 2 Radar WebKit Bug Importer 2023-12-19 14:11:02 PST
<rdar://problem/119892391>
Comment 3 Filipe Norte 2024-01-08 06:13:25 PST
Hi
Was wondering if anyone had the chance to make some progress on a fix for this issue? 
Thank you
Comment 4 Miguel Gomez 2024-01-17 05:27:25 PST
I've been debugging what's happening here, comparing the execution of the problematic test case with a similar one that sets a background color to the body instead of an image, which is working as expected. The background color case can be tested in

https://people.igalia.com/magomez/bodybackground/good-color.html

The GraphicsLayer tree generated in both cases is this:

7f5172003030 id 14 (0,0-1920,1080) 0.00KB (root) [opaque] RenderView 0x7f5172002d00 - updateBackingAndHierarchy
  7f5172000d40 id 19 (0,0-1920,1080) 0.00KB z-index: 0 (negative z-index children) [+foreground] RenderBlock 0x7f5172001720 HTML 0x7f51720012b0
    7f5172001810 id 18 (0,0-1920,1080) 0.00KB z-index: -1 (negative z-index children) [+foreground] RenderBody 0x7f5172001930 BODY 0x7f51720014b0 id='body'
        7f5172004720 id 15 (128,36-288,126) 0.00KB z-index: 1 (3D transform) RenderBlock (positioned) 0x7f5172004630 DIV 0x7f5172003cc0 id='test'


This is created because the body element has a zindex of -1 and inside there is the test div that's forced its own layer due to a 3D transform.

In both cases, when painting the contents of the body layer, RenderBox::paintBoxDecorations() won't paint its background (BackgroundPainter::paintsOwnBackground() returns false in BackgroundPainter::paintBackground()). This is because this code in BackgroundPainter::paintsOwnBackground():

// The <body> only paints its background if the root element has defined a background independent of the body,
// or if the <body>'s parent is not the document element's renderer (e.g. inside SVG foreignObject).
auto documentElementRenderer = renderer.document().documentElement()->renderer();
return !documentElementRenderer || documentElementRenderer->shouldApplyAnyContainment() || documentElementRenderer->hasBackground() || documentElementRenderer != renderer.parent();

In the case where we have a background color and not an image for the body (the case that works), the layer that's actually painting the background color is the root layer (14 in the list), through RenderView::paintBoxDecorations(). But when using the background image for the body (the case that doesn't work), this function just paints a transparent background and not the image. And the body layer doesn't paint the background image either, so in the end it's not shown.

RenderView::paintBoxDecorations() doesn't have the capability to render a background image. I wonder whether the proper thing to do here would be adding a BackgroundPainter to the class, so it can paint images as well. Or whether the fix should be some different approach. Any hints would be appreciated.
Comment 5 Filipe Norte 2024-01-17 06:09:35 PST
Thanks for the investigation so far on this, Miguel. In the issue described in https://github.com/WebPlatformForEmbedded/WPEWebKit/issues/1249, I was also able to reproduce the same problem using a background color, although it depends in this case on the presence of "DOCTYPE" (might be enabling some quirk).
Comment 6 Miguel Gomez 2024-01-17 07:31:40 PST
> RenderView::paintBoxDecorations() doesn't have the capability to render a
> background image. I wonder whether the proper thing to do here would be
> adding a BackgroundPainter to the class, so it can paint images as well. Or
> whether the fix should be some different approach. Any hints would be
> appreciated.

Another option would be allowing the body element to render its background if it has a background image. I'm testing this approach and it fixes the problem, but I'm not sure whether there can be some situation where it produces an erroneous result.