Closed Bug 627771 Opened 15 years ago Closed 7 months ago

Add dithering to gradient color transitions to address banding in 24-bit "truecolor"

Categories

(Core :: Graphics: WebRender, enhancement)

enhancement

Tracking

()

RESOLVED FIXED
145 Branch
Webcompat Priority P1
Tracking Status
firefox145 --- fixed

People

(Reporter: themoz, Assigned: mr.alexander.n.hill)

References

(Blocks 3 open bugs, )

Details

(Keywords: webcompat:platform-bug)

User Story

platform-scheduled:2025-09-30
user-impact-score:20

Attachments

(3 files, 13 obsolete files)

2.20 KB, text/html
Details
1.30 MB, image/png
Details
48 bytes, text/x-phabricator-request
Details | Review
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10 Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10 This is wishful thinking, but please consider adding a dithering algorithm to the gradient rendering (for example, as used by -moz-linear-gradient). The limited colors available in 24-bit "truecolor" cause visible banding regardless of the presence of alpha. In Firefox, the banding is especially perceivable with vertical gradients. This is because web content so often scrolls vertically. The color transitions are made more recognizable when scrolling/moving the content. Bug 619834 cites banding when alpha is used, but the banding exists in both cases. Banding is perhaps more severe with alpha or affected by an unrelated bug, but that's not the matter at hand here. The test case I am attaching shows vertical gradients and the subtle but nevertheless quite recognizable color transitions. These are visible on Windows 7; I have not tested any other platform. I don't know anything about the internals of Gecko's gradient rendering, but if a dithering algorithm were somehow introduced, this minor issue could be eliminated. As an aside, weren't 30-bit or 32-bit color depths introduced in the 1990s? It's a pity we're still stuck with 24-bit. Reproducible: Always Steps to Reproduce: See test case. Actual Results: On Windows 7, visible color transitions are seen. Expected Results: With 32-bit color, the transitions would be imperceptible. In 24-bit color, a dithering algorithm could help achieve the same result.
Component: Layout: View Rendering → Graphics
QA Contact: layout.view-rendering → thebes
Perhaps, a new css attribute which specify how much dithering to use. background: -moz-linear-gradient(left, #E7E7E2, #CDCDCD, dither: 20%);
I just noticed this on youtube's background, which uses a #555 to #333 greyscale gradient. That only yields 34 possible color stops over several 100 pixels in height, i.e. it's noticeable. Dithering certainly would help here.
QA Contact: thebes → jmuizelaar
See Also: → 1001455
It looks like this could be beneficial for b2g memory usage. See bug 1001455. Is there any way to get it on the roadmap?
Status: UNCONFIRMED → NEW
Ever confirmed: true
Flags: needinfo?(milan)
The author of madVR recently evaluated/implemented several dithering algorithms for dithering 16bit video in realtime (via GPU shaders) to 8bit. A modified form of ordered dithering called void-and-cluster was found to be trivial to parallelize (unlike various error diffusion algorithms), leaving no visible patterns (unlike ordered dithering) and without introducing too much visual noise (unlike random threshold dithering).
This sounds like the right thing to do - can we get "product" to ask for this and explain the benefits? I see them, but I'm not sure I'm representative of the overall Firefox audience :) Maybe somebody from UX?
Flags: needinfo?(milan)
This should be resolved once webrender is enabled, per https://github.com/servo/webrender/pull/966
What's the progress on this issue now? I can see the PR was merged last year, but I still see some banding in gradients when comparing with Safari, where gradients are flawlessly smooth. Not sure if the current rendering is the result after an improvement, or do we have more ways to go?
(In reply to Hansol Kim (zvuc) from comment #10) > What's the progress on this issue now? I can see the PR was merged last > year, but I still see some banding in gradients when comparing with Safari, > where gradients are flawlessly smooth. Not sure if the current rendering is > the result after an improvement, or do we have more ways to go? It's dependent on WebRender being enabled in Firefox, which is currently still in development. If you're on Nightly, you can enable WebRender by going to about:config and setting gfx.webrender.all to true.

Is this still being worked on? I've turned on gfx.webrender.all on the latest Nightly version and light gradients all seem fine, but there is still very noticeable banding on dark gradients. Chrome does not have this issue.

Minimal example:

body, html {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    background: radial-gradient(circle, #1D1B43, #12102C);
}

(In reply to cengels from comment #12)

Is this still being worked on? I've turned on gfx.webrender.all on the latest Nightly version and light gradients all seem fine, but there is still very noticeable banding on dark gradients. Chrome does not have this issue.

It was recently disabled in webrender due to test failures when we started using direct composition[1]. We have some workarounds we were just recently batting around, though. I can't guarantee I can work on this in the near future but if I get any spare time I will.

[1]: In case anyone needs the technical details: as I understand it, when we do direct composition, we get handed an offset into a texture atlas - however, we apply our dithering texture based on gl_FragCoord, which means the exact dithering offset is non-deterministic, and thus when comparing with a reference, the two things mismatch on that offset, producing a delta which exceeds our fuzziness limit. The fix ought to be simply supplying and using the compositor-provided offset into the texture atlas in our shaders. Glenn can correct me on this if I got it wrong.

Hi,

Most other major browsers have gradient support and dither gradients - they look nice and smooth on Chromium-based browsers. It would be such a time saver to be able to use gradients programmatically.

  • The lack of dithering is especially noticeable when fading between two colors within 15-25 brightness, in terms of HSB. Take, for instance, this linear gradient:
body {
    background: linear-gradient(62deg, #364739, #1E2923);

    /* Making the gradient continuous */
    background-repeat: no-repeat;
    background-attachment: fixed;
}
  • This bug references Windows 7, though this is reproducible on Windows 10.

I'd be very grateful to see this fixed. Thanks.

Flags: needinfo?(jmuizelaar)

This is really a disgrace. The bug was opened 11 years ago, as it seems Firefox has gotten at least one major overhaul with its rendering engine, consumer monitors now offer 10 bits per channel, HDR has become somewhat mainstream - yet here we are having color banding issues, only in Firefox.

What compounds the issue is that modern color space awareness makes it even harder to match manually created gradient images with an included dithering to other HTML elements really hard.

I made a small batch file to automatically create gradients with the necessary dithering, to at least not having to fumble around with Photoshop or GIMP:

magick convert -define png:format=png64 -depth 16 xc:rgb(7.5,7.5,7.5) xc:rgb(18,18,18) xc:rgb(7.5,7.5,7.5) +append -filter Cubic -resize 2048x8! -profile sRGB.icc gradient.png
magick convert gradient.png -channel RGB -separate -ordered-dither o8x8,256 -colors 256 -combine -define png:format=png8 -profile sRGB.icc gradient_dithered8.png

Hope that helps someone, until Firefox finally catches up to the rest of the browsers.

In my opinion it would be better to not support gradients at all than to support it without dithering. At least then authors can use a media query to use a fallback that doesn't look nasty.

Have just created an enhancement bug for that: https://bugzilla.mozilla.org/show_bug.cgi?id=1749560

After looking into this a bit more, I realise that the CSS specification did not allow dithering until December 2020. Perhaps one of the reasons this bug has not gained any traction in the last 11 years is a perceived need to adhere strictly to the spec.

However since December 2020 (this commit: https://github.com/w3c/csswg-drafts/commit/0753dd1eb3d3dfc3784db82830380ce7c9d15989) dithering has been allowed. Other browsers have dithered since well before, if not always.

Does this change anything?

Severity: normal → S3

Hi. I am part of the Novation Components team. Since Web MIDI is coming to Firefox shortly, we've started to make sure that Components behaves correctly on Firefox. Apart from some open bugs on Web MIDI our biggest issue right now is our usage of relatively subtle gradients that produce a ton of color banding on Firefox because of the missing dithering.

It would be great if you could reconsider the priority of this (I am aware of https://bugzilla.mozilla.org/show_bug.cgi?id=1608741). Especially when used subtly like this, gradients really look quite dated on Firefox.

Here's a screenshot of our front page (I'm linking to prevent image resizing here):

https://uploads.halfbyte.org/uploads/47ec96ec95f3807ff9e3/Screenshot%202022-12-06%20173959.png

Duplicate of this bug: 1804821

The gradients in Firefox look really awful! 🤢🤮

I often see that Firefox does not display gradients smoothly, but with noticeable steps. That was on Windows and now on macOS 🤦‍♂️ You can see it very well on this site (the radial gradient around the mouse doesn't look smooth like it does with Chrome and Safari): https://www.roccat.com/collections/gaming-mice

Firefox: https://i.imgur.com/Ip7bPnC.png
Chrome: https://i.imgur.com/8J5rjXd.png
Safari: https://i.imgur.com/vDlhqxW.png

It also immediately catches the eye on a popular site called Imgur. Here is a link as an example: https://imgur.com/a/MkPl9aR

Firefox: https://i.imgur.com/i3QvqlK.png
Chrome: https://i.imgur.com/bt7VQun.png
Safari: https://i.imgur.com/Ftmw6Tv.png

Was just about to file a new bug when I noticed this one. I've come across the same thing with a site I've been developing, darkish gradient looks fine in Chromium-based browser but banded in Firefox.

Test case: https://game-point.net/misc/fxBanding/
Chromium-based screenshot: https://game-point.net/misc/fxBanding/brave.png
Firefox screenshot: https://game-point.net/misc/fxBanding/firefox.png

Duplicate of this bug: 619834
Duplicate of this bug: 1840447

The fact that it has been 14 years and there is still banding on all basic gradients whether it be CSS or SVG is crazy, in my opinion this is such a basic function that it needs to be addressed.

CSS gradient going from #2d2d2d to #000000 at an angle of 160deg, at 1440p, left is Firefox right is Chrome.
https://imgur.com/a/rx9LsDf

SVG gradient going from #323232 to #000000, at 1440p, left is Firefox right is Chrome.
https://imgur.com/a/SO6P3hW

Can also be viewed and fullscreened here for testing:
https://coolors.co/gradient-maker/323232-000000

Would be great to finally have smooth transitions and nice glow effects.

See Also: → 1943302
Blocks: 1889092
See Also: → 1749560
Webcompat Priority: --- → ?

This would be a potentially high impact webcompat bug to solve - we have several other bugs reported more recently that report the same or similar things.

OS: Windows 7 → All
Hardware: x86 → All

FYI: There is also a request on Connect asking for fixing this:
https://connect.mozilla.org/t5/ideas/dithering-for-gradients/idi-p/15120

(In reply to Glenn Watson [:gw] from comment #40)

This would be a potentially high impact webcompat bug to solve

We don't really have a good way to quantify this. Our system is supposed to have one site report bug per instance, and we don't have this here. In most cases, we'd triage them as minor-visual, which would have a very low priority. We also can't really use telemetry data or anything, because a lot of gradients on websites are on small things like a button, where you wouldn't notice it.

But of course, linear gradients are also used in large backgrounds (Tailwind-based sites are a good example), and you absolutely see the difference there. Nothing is broken per-se, but it looks super bad. If we had individual site reports for all of these, this bug would probably be a clear P1.

I'll set webcompat-priority P1 for now, because it makes Firefox looks really bad. We should at least spend some time checking if we can fix this with a reasonable amount of time.

Webcompat Priority: ? → P1

(In reply to Krzysztof from comment #45)

I'm afraid that our friends from youtube added such a gradient to video, and now it's impossible to watch it for some people.

https://www.reddit.com/r/firefox/comments/1ipx4j6/comment/mcvmoob/

That's an unrelated problem. Can multiple people reproduce that?

(In reply to Jeff Muizelaar [:jrmuizel] from comment #47)

That's an unrelated problem. Can multiple people reproduce that?

There was a second Reddit post about the same issue. A few people in the comments seem to also be experiencing it.

(In reply to Jeff Muizelaar [:jrmuizel] from comment #47)

(In reply to Krzysztof from comment #45)

I'm afraid that our friends from youtube added such a gradient to video, and now it's impossible to watch it for some people.

https://www.reddit.com/r/firefox/comments/1ipx4j6/comment/mcvmoob/

That's an unrelated problem. Can multiple people reproduce that?

That's privacy.resistFingerprinting doing what it's supposed to do.

Also, to the other folks: Please do not use this bug to post "me-too" responses. It won't make this bug go any faster, but what it will do is it might get your account deleted, or it might get this bug locked so nobody can post comments, even people who wanted to participate productively. So please don't.

I noticed that currently enable_dithering is set to false in the initialization code for WebRender: https://searchfox.org/mozilla-central/source/gfx/wr/webrender/src/renderer/init.rs#227

Is there a reason this wasn't set to true?

I noticed that currently enable_dithering is set to false in the initialization code for WebRender: https://searchfox.org/mozilla-central/source/gfx/wr/webrender/src/renderer/init.rs#227

From my understanding is that this flag adds the following feature:
https://searchfox.org/mozilla-central/source/gfx/wr/webrender/src/renderer/shade.rs#712

But is apparently isn't used anywhere else... Maybe it just wasn't finished being implemented?

The original source code for WebRender on github does have a completed implementation. But I do not understand which version of this was selected for Firefox and why it wasn't updated or diverged. I am not familiar with FF development.

It was set to false because it introduced problems when we were working on compositor integration.

Flags: needinfo?(jmuizelaar)

(In reply to Jeff Muizelaar [:jrmuizel] from comment #53)

It was set to false because it introduced problems when we were working on compositor integration.

Are these problems still up to date and where can I find information about them and the progress that was made?

Component: Graphics → Graphics: WebRender
Flags: needinfo?(bhood)

(In reply to Jeff Muizelaar [:jrmuizel] from comment #53)

It was set to false because it introduced problems when we were working on compositor integration.

Is this set here? Would testing the feature be as simple as setting it to true? (Or, is there a reason this couldn't be an option in about:config or something to test without recompiling?)

https://searchfox.org/mozilla-central/rev/45d158e24489a6bad5a2d2d384b5083595c6c29c/gfx/wr/webrender/src/renderer/init.rs#227

It's worth trying. The functionality may have rotted to some degree since it was added.

I just tried to recompile with the flag enabled and I didnt see any changes...

Think I found the issue. Dithering impl itself seems fine, it looks like there's a failure in passing the DITHERING feature when compiling one of the shaders, making a link error when enable_dithering is set to true.

I'm gonna see about fixing it & doing a PR or whatever it's called to submit a patch

swgl_drawSpanRGBA8 seemed to be drawing over the code that draws the gradient (and optionally handles dithering). It doesn't seem to do much graphically, so I've #ifdef'ed it away for the case of dithering, but I'm open to discussion. I'm new to firefox dev, so if it's doing something that I'm not aware of please let me know! (This is also why the review is blocking.)

Dithering doesn't seem to use the EXT_YUV_target extension.

Attachment #9488529 - Attachment is obsolete: true

swgl_drawSpanRGBA8 seemed to be drawing over what's drawn by brush_fs(). It doesn't seem to do much graphically, so I've #ifdef'ed it away for the case of dithering, but I'm open to discussion. I'm new to firefox dev, so if it's doing something that I'm not aware of please let me know! (This is also why the review is blocking.)

Assignee: nobody → mr.alexander.n.hill
Status: NEW → ASSIGNED
Attachment #9488530 - Attachment is obsolete: true

Dithering doesn't seem to use the EXT_YUV_target extension.

Blocks: 1968618

Just to sort of update people on what's going on, in case anyone's curious:
I'm working on this bug on and off. The main thing I'm doing now is making the span software rendering system support dithering for linear gradients. In my original PR I just had it disabled, but obviously that's a terrible idea for performance.
I had made a mess of the Phabricator listing (since I don't really understand that platform). I may obsolete all of my current listings and create a new one when I have all the final code.

As for why this is taking so long, I'm pretty busy during the week and only have a little bit of time each weekend. But we're getting close!

Alex, have you consider checking out https://github.com/servo/webrender/pull/1042 ? It may be related

Thanks - it's possible that was why it was originally disabled, I don't know. The surrounding code has changed a lot since then, and mechanic for disabling dithering has apparently changed.

Anyway, I arrived at a working build some time ago and have been putting off going through the logistics of submitting through phabricator. Maybe in the next few days I'll:

  1. make sure I haven't missed anything
  2. Organize and submit the patch
See Also: 1749560
Attachment #9488538 - Attachment is obsolete: true
Attachment #9488534 - Attachment is obsolete: true
Attachment #9488533 - Attachment is obsolete: true
User Story: (updated)

The rounded uint16_t solution created inconsistencies in the gradient that were masked by banding.
I'm filing this under the same bug as the dithering implementation because it relates to parity between the hardware-rendered and software-rendered gradients. Up to discussion.

Attachment #9497754 - Attachment description: Bug 627771: Implement software dithering r=gw → Bug 627771: Implement software dithering for linear gradients r=gw
Attachment #9497912 - Attachment is obsolete: true
Attachment #9497923 - Attachment is obsolete: true
Attachment #9497938 - Attachment is obsolete: true
User Story: (updated)
Attachment #9497754 - Attachment is obsolete: true
Attachment #9497925 - Attachment is obsolete: true
Attachment #9497966 - Attachment is obsolete: true
Attachment #9497940 - Attachment is obsolete: true
Pushed by imoraru@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/eb842169586f https://hg.mozilla.org/integration/autoland/rev/6e6daa8446fa Revert "Bug 627771 - Implement SWGL fast-path dithering for linear and radial gradients. r=lsalzman" for causing linux base toolchains build bustages.

Revert for causing linux base toolchains build bustages.

User Story: (updated)
Flags: needinfo?(mr.alexander.n.hill)

(In reply to Iulian Moraru from comment #78)

Revert for causing linux base toolchains build bustages.

Fixed now.
What's the needinfo flag about here? I'm a bit confused.

Status: ASSIGNED → RESOLVED
Closed: 7 months ago
Resolution: --- → FIXED
Target Milestone: --- → 145 Branch

I just saw that this is fixed! Thank you to Alex Hill and the other developers, and to the various advocates for shining attention on this request.

QA Whiteboard: [qa-triage-done-c146/b145]
Flags: needinfo?(mr.alexander.n.hill)
Attachment #9497763 - Attachment is obsolete: true
Blocks: 2000770
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: