Opaque image elements with backgrounds may show the background at the edges |
|||||||
Issue descriptionWith the changes for 650455, ImageDocument now displays images with a checkerboard background. Unfortunately, sometimes the background is larger than the actual image being displayed on mobile devices (I haven't been able to repro this on desktop Chrome). I've tried just displaying the image on the page un-centered, but the problem still seems to come and go as you zoom in and out. I'd speculate that it's a problem with rounding somewhere, but I'm not sure how to debug. Sending to pdr@ for triage per email thread.
,
Nov 5 2016
,
Nov 5 2016
Total hack, but I wonder if "will-change: transform" on the image style would be a reasonable workaround until this is fixed?
,
Nov 5 2016
Tentatively assigning.
,
Nov 5 2016
Setting "will-change: transform" in the ImageDocument case changed things a little bit, but I ended up with a single-pixel high line of the same color all the way across instead of the checkerboard pattern. Not entirely sure how that ended up that way.
,
Nov 10 2016
The new image page will be rolling out to beta in a week so it would be great if we could fix it. I'm not sure how though.. @Stephen, do you have any ideas on what to do here?
,
Nov 15 2016
I was able to make a stable repro that works on linux too: 1) Visit http://jsbin.com/kurugo 2) Open the inspector, enable device emulation 3) Ensure the zoom is non-zero. This can be done by picking a phone larger than your monitor (maybe iphone 6 plus), or selecting a non-100% zoom value from the dropdown. 4) Refresh the page 5) Notice the white borders. This reproduces for me on mac, linux, and a GalaxyS6.
,
Nov 16 2016
I confirmed this isn't blink and the skp is correct. I wonder if this could be related to image hijacking? +cc Florin and Vlad, do you have any ideas?
,
Nov 16 2016
Is this something that is specific to the inspector or is the problem the same on the actual device? I'll see if image hijack is to blame here.
,
Nov 16 2016
This happens on actual devices. I have a dpr=4 and a dpr=2 device and both are affected.
,
Nov 16 2016
We always draw with anti-aliasing enabled these days. So if the image and bg are not pixel aligned (due to external/emulation transform or DSF), the edge bleed is not surprising. The only ways to avoid bleeding would be to either turn off AA or ensure the dest rect is always pixel aligned in device space. Or determine that we shouldn't draw the background at all because the image is opaque (IIRC we have heuristics for that, but they don't play nice with lazy decoded images). I suspect --enable-use-zoom-for-dsf would help the Android case, but maybe not the emulation repro.
,
Nov 16 2016
I've confirmed that steps in #7 repro both with and without image hijack canvas. Florin, do you mind taking a look since it seems like you know where the problem is?
,
Nov 16 2016
@fmalita, is there something different about device scale factor compared to just transforms? For example, this has snapping issues on mac&android but not linux (even with --force-device-scale-factor=2): http://jsbin.com/wurimi To make sure I understand... the image is special-cased to not use AA, whereas the background uses AA? I think we'll play bug wack-a-mole if we have various parts of the pipeline using different AA choices. For example, fixing image+background might lead to bleed with borders or sibling elements on the page. If ganesh is enabled, is it too expensive to draw the image with the same AA as the background?
,
Nov 17 2016
We always enable AA, for both image and background draws. The bleed is not due to differences in AA config, but is a fundamental property of how AA is implemented: coincident AA edges don't occlude 100% - each coverage-based AA application blends against a fraction of the previous AA. Here's one of your examples, tweaked to use plain background colors instead of images: http://output.jsbin.com/xudadagimu It is bleeding, as expected, in both the device view + zoom case and regular Android view (see attached). (the inspector/device emulation repro may be a distraction, because I'm not convinced it exercises the same transform logic as DSF; let's focus on DSF-only repros only) DSF used to be implemented as an "external" transform, applied at rasterization time and mostly invisible to Blink. So while we could compensate for explicit transforms (which seems to be the case based on observed behavior), we didn't do the same for DSF. But oshima@'s awesome --enable-use-zoom-for-dsf is changing all that: DSF gets applied as a zoom factor, visible to Blink, and we can pixel-snap correctly. use-zoom-for-dsf is currently turned on by default on ChromeOS, Win and Linux IIUC: https://cs.chromium.org/chromium/src/content/common/content_switches_internal.cc?rcl=0&l=23. That should explain the different behavior you're seeing on Android/Mac. So I'll have to verify on Android, but I think --enable-use-zoom-for-dsf is the correct fix. +oshima@
,
Nov 17 2016
Tried --enable-use-zoom-for-dsf on Android, and it doesn't seem to make a difference (at least not with content_shell). @oshima, is --enable-use-zoom-for-dsf expected to work on Android? @pdr, can you try --enable-use-zoom-for-dsf on Mac and see if it makes a difference?
,
Nov 17 2016
not yet. We just enabled it on linux in 54. Mac/Android would be next, but we don't have enough resource/ppl to look into them right now. If you or someone can volunteer either for mac or android, please let me know.
,
Nov 17 2016
@fmalita, thanks for the explanation. Can you think of a way to workaround this for dfalcantara's image document project? If you have a hidpi android device, just visit https://i.ytimg.com/vi/zbPdM15zGEA/hqdefault.jpg in Chrome Canary to see the bug :/
,
Nov 21 2016
pdr: Since the background color is occluded, the page author could just remove that style. Alternatively, the paint code could not paint the background if the image is loaded (although that makes some future image decisions more complicated).
,
Nov 21 2016
enne, dfalcantara and I are the page authors. This code is for the image view (both android and desktop are now live with it). It's done to support transparent images such as https://pr.gg/happy.png. I don't think there is another way to do this.
,
Nov 21 2016
@pdr I can think of hacks - if it's not super important for the background size to match the image size exactly, maybe shrink the checkerboard background by a few units and hope that's enough for all DSFs? Can you check whether --enable-use-zoom-for-dsf makes a difference on Mac for your repro? For some pinch-zoom levels, the bleed on https://i.ytimg.com/vi/zbPdM15zGEA/hqdefault.jpg looks more serious than just AA bleed, so maybe there's more than that going on. Looks like the computed checkerboard size might be out of sync with the image size for some scales?
,
Nov 21 2016
I'm somewhat concerned with the overhead introduced by this feature; looks like we're overdrawing the whole image area *twice* (unnecessarily for opaque images, which is presumably the common case): white solid color layer + checkerboard image layer (expensive paint, two nested shaders: picture shader wrapping a gradient shader). https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/ImageDocument.cpp?rcl=0&l=421 At the very least we could drop the white layer and adjust the gradient (#eee/#fff instead of #eee/transparent), no?
,
Nov 21 2016
Setting it to #fff instead of transparent breaks the checkerboard pattern: it relies on overlapping the two background images to render the squares.
,
Nov 21 2016
Ah, yeah, clever gradient trick. But ouch, that means our background decoration is *three* overdraws with two expensive shaders!?
You can still drop the white solid color layer though, this seems to produce the equivalent pattern:
--- a/third_party/WebKit/Source/core/html/ImageDocument.cpp
+++ b/third_party/WebKit/Source/core/html/ImageDocument.cpp
@@ -419,11 +419,10 @@ void ImageDocument::updateImageStyle() {
imageStyle.append("px;");
imageStyle.append(
- "background-color: white;"
"background-image:"
"linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, "
"#eee 75%, #eee 100%),"
- "linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, "
+ "linear-gradient(45deg, #eee 25%, white 25%, white 75%, "
"#eee 75%, #eee 100%);");
}
}
Can we do even better thought? Maybe inline a 2x2 dataURI image? I'll take a stab.
,
Nov 21 2016
--- a/third_party/WebKit/Source/core/html/ImageDocument.cpp
+++ b/third_party/WebKit/Source/core/html/ImageDocument.cpp
@@ -419,12 +419,10 @@ void ImageDocument::updateImageStyle() {
imageStyle.append("px;");
imageStyle.append(
- "background-color: white;"
- "background-image:"
- "linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, "
- "#eee 75%, #eee 100%),"
- "linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, "
- "#eee 75%, #eee 100%);");
+ "image-rendering: pixelated;"
+ // 2x2 white/#eee checkerboard background
+ "background-image: "
+ "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAF0lEQVQI12P8////+/fvGd69e/f//38AURkLk8MtdjoAAAAASUVORK5CYII=);");
}
}
^ this would work beautifully if not for the pesky filter quality: we need nearest neighbor to avoid blurrying due to scaling. image-rendering: pixelated; does it, but unfortunately it applies to both the background and the actual image content. AFAIK there's no attribute to control the background filter quality in isolation.
An alternative would be to generate and encode a checkerboard tile sized appropriately, on the fly. But that's kind of a PITA, so probably not worth pursuing unless raster performance for image docs is a real issue.
,
Nov 22 2016
@fmalita, re: comment #20: >Can you check whether --enable-use-zoom-for-dsf makes a difference on Mac for your repro? Unfortunately --enable-use-zoom-for-dsf doesn't seem to fix things on mac. >For some pinch-zoom levels, the bleed on https://i.ytimg.com/vi/zbPdM15zGEA/hqdefault.jpg looks more serious than just AA bleed, so maybe there's more than that going on. Looks like the computed checkerboard size might be out of sync with the image size for some scales? The background image should cover the entire image so I think this might just be an illusion. Is there a way to confirm that? (florin, please look away) I wonder if we could do something incredibly gross such as 2 additional gradients to restrict the gradients to be inset by 2px? Here's an example: http://jsbin.com/hepayab
,
Apr 27 2017
Not a P1 at this stage. The artifact is annoying but not enough to block a release on or tie ourselves to fix within 30 days. |
|||||||
►
Sign in to add a comment |
|||||||
Comment 1 by pdr@chromium.org
, Nov 5 2016Components: Blink>Paint
Status: Available (was: Untriaged)
581 bytes
581 bytes View Download