Bug 200711

Summary: Color Range 24bpp (True Color) fix for Intel Graphics over DisplayPort
Product: Drivers Reporter: Nicholas Stommel (nicholas.stommel)
Component: Video(Other)Assignee: drivers_video-other
Status: RESOLVED MOVED    
Severity: high CC: daniel, jani.nikula, tom.ty89, ville.syrjala
Priority: P1    
Hardware: Intel   
OS: Linux   
Kernel Version: 4.17.11 Subsystem:
Regression: Yes Bisected commit-id:
Attachments: True Color 24bpp patch for Intel Graphics over DisplayPort

Description Nicholas Stommel 2018-08-02 07:10:51 UTC
Created attachment 277659 [details]
True Color 24bpp patch for Intel Graphics over DisplayPort

For some background, this bug has been relevant since roughly 2015, tangentially relevant to bug #94921, however entirely different in its proposed fix. The Intel kernel drivers automatically determine the output RGB range correctly for HDMI displays regardless of bits-per-pixel color depth, but fail to set full RGB output range appropriately for DisplayPort monitors using 24-bit True Color, like the Samsung CF591 I am currently using and the other two HP monitors in my possession. All I can say is oh my God...it was in front of us all this time. 

Best of all, the fix does not interfere with any of the neat Intel display "automagic" concerning proper color range settings based on CEA and VESA specs. The critical flaw concerns a single line in the drivers/gpu/drm/i915/intel_dp.c file, and only pertains to native Displayport sinks on displays that deliver 24-bit True Color on Intel integrated graphics. Namely, it is an unforseen, long-time regression of the Automatic RGB mode added to the Intel graphics stack around five years ago: https://lists.freedesktop.org/archives/dri-devel/2013-January/033576.html

In response to Tom Yan's frustration in bug #94921, all I can say is that Intel's automagic *DOES* work on the HD 630 iGPU, it simply fails to account for the fact that higher-end IPS and VA panels (the ones I tested and the one I currently use) may have higher than 18 bpp (bits-per-pixel) color depth. Simply accounting for 24-bpp (True Color) in a single conditional line results in full-range RGB displayed beautifully and correctly on my monitor. Without this fix, using a native DP connection through integrated Intel graphics on Linux is no joke unusable without manually setting correct color depth, which isn't even currently possible in Wayland. 

Given the wide range of 24-bit True Color monitors available (most any newer panels that support 16.7 Million colors) this seems like a necessary and fully compatible solution to our display woes. This is a *one-line* lifesaver of a patch. My display looks ridiculously washed out in comparison, without full-range color applied. Here is the "why" behind the problem: currently, a single conditional statement erroneously sets RGB Color Range on 24bpp DP sinks to Limited instead of Full because only 18bpp DP sinks are properly accounted for.

Initially I had tried tracing the function on the next line all the way back through the i915 and drm modules, but the problem was staring at me right in the face. Intel, please merge this patch upstream to account for True Color displays using a Displayport connection on Intel integrated graphics. My 24-bpp Samsung CF591 monitor as well as my two other HP monitors are actually *usable* in Linux over Displayport again! No impossible Wayland woes, no annoying X woes, no plymouth KMS woes. This is nothing short of fantastic! The patch attached works on the latest mainline kernel v4.17.11 and I expect to see the fix applied upstream as soon as possible.
Comment 1 Tom Yan 2018-08-02 12:08:43 UTC
Essentially your patch means to avoid using limited range as default for "all DP in reality", which is one of the approaches I proposed, so good luck having Intel accpeting it. (No offense but the extra check makes less sense than just equate auto to full.)

To be honest I don't expect Intel to fix it (by avoiding limited as default) anyway. The DP spec is just some braindead cheap copycat work from some idiot (VESA) that tried to dominate the world but failed (after all those years HDMI just exists and evolve parallelly on the AV world, with DP do only on the computer word), so there's not a real point in arguing whether Intel is doing the right thing or wrong thing.

I think we deserves something like per-port sysfs for the attribute though. I hope someday someone would do it. Couldn't care less though, as I did enough for this as a human being (while some people can earn money by keep producing garbage driver).
Comment 2 Tom Yan 2018-08-02 12:29:31 UTC
pipe_config->limited_color_range = false
Comment 3 Nicholas Stommel 2018-08-02 16:43:34 UTC
No, the patch does NOT mean avoiding limited range as default for "all DP in reality", as the drm CEA mode check line is still very much in place and working correctly. And frankly, I rather like DisplayPort as a video standard, Tom. It is under no circumstances "some braindead cheap copycat work". For some uses, dual DP++ is far superior to HDMI. This fix does NOT default set the RGB range to full over any DP connection like setting 

pipe_config->limited_color_range = false. 

Accounting for 24bpp displays (just as 18bpp displays are accounted for) in the conditional statement under regarding automatic color range selection INTEL_BROADCAST_RGB_AUTO) and setting limited_color_range to false entirely adheres to the Intel spec. Furthermore, the color range WILL be correctly be set to limited on DP connections that do not adhere to the VESA spec in

drm_default_rgb_quant_range(adjusted_mode) == 
HDMI_QUANTIZATION_RANGE_LIMITED;

This is a constructive and important matter for many 24bpp True Color displays that is itself an entirely different bug than #94921. Furthermore, the small patch keeps all of Intel's automatic mode selection work entirely in place. I would appreciate some input from Intel here, as this is evidently something that can and should be changed.
Comment 4 Nicholas Stommel 2018-08-02 16:58:09 UTC
Constructive input from Intel here would be nice. I would appreciate if we could keep the conversation limited to 24bpp True Color being correctly handled over DP, regardless of Tom's feelings towards/remarks concerning Intel. This is very much a relevant and fixable issue that doesn't demand any kind of radical changes on the Intel driver side. CEA/VESA mode detection clearly works as intended, with the exception of the case of DisplayPort 24bpp displays (as evident in the minor edit of the conditional statement in the patch).
Comment 5 Nicholas Stommel 2018-08-02 18:20:28 UTC
To be clear: this is not a feature request. It is most certainly a bug, perhaps one that only became evident when 24bpp True Color monitors became widespread. As it stands before the patch, DP sinks on 24bpp True Color displays erroneously fail the part of the color range conditional check, always setting the output RGB range to washed-out limited 16:235. The expected and correct behavior in full adherence to the VESA/CEA spec is outputting the full 0:255 RGB color range over DisplayPort on 24bpp True Color displays. Intel, I respectfully ask of you to fix this issue, with something like the minor patch I attached.
Comment 6 Nicholas Stommel 2018-08-02 20:59:18 UTC
 (In reply to Tom Yan from comment #1)
> Essentially your patch means to avoid using limited range as default for
> "all DP in reality", which is one of the approaches I proposed, so good luck
> having Intel accpeting it. (No offense but the extra check makes less sense
> than just equate auto to full.)

Oh...wait. My logic was incorrect indeed. Tom is basically right here, as what is CURRENTLY happening in the conditional statement means ANY DP 18bpp display (and with my small patch ANY DP 24bpp display) will result in an immediate short-circuit boolean 'false' value, setting pipe_config->limited_color_range = false. See the unpatched condition below: 

pipe_config->limited_color_range =
  bpp != 18 &&
  drm_default_rgb_quant_range(adjusted_mode) ==
  HDMI_QUANTIZATION_RANGE_LIMITED;

On further inspection, Intel currently isn't even testing whether displays with 18bpp adhere to the CEA/VESA spec, as the function drm_default_rgb_quant_range(...) is never actually executed. Which just makes me confused. Why should those of us with 24bpp True Color or 30+bpp HDR displays *not* be getting full-range color? It doesn't even make sense. So now I suppose we are right back where we started at bug #94921. 

I do believe this particular harcoded hack "bpp != 18" is, however, a bug. 24bpp displays should receive equal treatment in that 24bpp DP displays should short-circuit in the logic statement above to limited_color_range = false, just the same as 18bpp DP displays currently do. I implore someone at Intel to address this issue. I simply cannot use native DP on Linux without literally recompiling the kernel every single point release.
Comment 7 Nicholas Stommel 2018-08-03 02:08:45 UTC
Realizing the truth of the matter here by examining the logic with a more...rational eye, if 18bpp displays unconditionally receive full-range 0:255 RGB color, then 24bpp True Color displays should as well. No 24-bit 16.7 million color display that takes DisplayPort-in even expects something besides full range RGB. The second condition involving a function call that checks display modes is, as Tom correctly pointed out and I originally failed to see, not even evaluated for 18bpp displays and the current code simply does not make logical sense. I just want my computer to properly display color, instead of washed-out soupy gray-black. As an Intel customer with no other options available, I am stuck in this situation just as, I expect, many other users have been for several years. Please at the very least look into this issue. If I had known how bad the situation was, I never would have purchased this computer months ago, but I couldn't have known that and certainly won't be able to produce the funds for another computer in quite some time. This matter is one of great disappointment and dissatisfaction, but I fear there is nothing that will be done :(
Comment 8 Nicholas Stommel 2018-08-03 07:26:27 UTC
I may have made myself look like something of a fool here, but the very nature of that one inverted boolean statement in comment #6 found in intel_dp.c is misleading. The logic is fundamentally flawed and self-deceiving on Intel's part because 18bpp displays are *not even checked* for VESA/CEA mode compliance as the statement short-circuits to false after evaluating bpp != 18, ignoring the "automagical" function call entirely. This seems for all intents and purposes a hardcoded hack implemented five years ago that doesn't consider the possibility of 24 or 30+ bit color depth over DP connections. 

As it stands, the code does not account for True Color or Deep Color/HDR displays whatsoever. My patch simply enforces skipping VESA compliance checks just as the "bpp != 18" clause already does, unless perhaps the bpp alone can determine the appropriate color range (which isn't so far fetched in the 2013 white paper). This upsetting color range bug does need a fix, even if it's not in the manner I originally approached it. I apologize if I have been overzealous in my demands (I'm pleading somewhat desperately here), but honestly fixing this single problem would be immensely helpful for many Linux users who rely on integrated Intel graphics.
Comment 9 Nicholas Stommel 2018-08-03 21:36:11 UTC
Due to the confusion surrounding some of my original posts which I am unable to edit, and the fact this bug was filed in the wrong place to begin with, I have moved it to appropriately to https://bugs.freedesktop.org/show_bug.cgi?id=107476