<div dir="ltr"><div><span style="font-size:14px">(Resent cause of moderation)</span></div><div><span style="font-size:14px"><br></span></div><span style="font-size:14px">This implements a highly needed feature in a minimal non instructive way. Consider a Limited Range display (like most TVs) where you want to watch a decoded video. The TV is set to limited range and the intel driver also uses full scaling Limited 16:235 mode, e.g. if you display the gray value 16 - the driver will postprocess it to something like ~ 22.</span><div style="font-size:14px"><br></div><div style="font-size:14px">The following happens currently in linux intel video world:</div><div style="font-size:14px">Video is decoded with e.g. vaapi, the decoded surface is either used via EGL directly in Limited Range. Limited Range processing takes place and at the end while rendering the intel driver will scale down the limited range data again as it cannot distunguish of the data it gets when e.g. rendering with OpenGL like we succesfully do in kodi.</div><div style="font-size:14px"><br></div><div style="font-size:14px">Another use case is vaapi when using the old vaCopySurfaceGLX (vaPutSurface) which would automatically use BT601 / BT709 matrix to upscale the content without any dithering to Full Range RGB. Later on this is scaled down again with the Limited 16:235 setting and output. Quality degrades two times.</div><div style="font-size:14px"><br></div><div style="font-size:14px">Users and applications widely used want to make sure that colors appear on screen like they were processed after the last processing step. In video case two use cases make sense:</div><div style="font-size:14px"><br></div><div style="font-size:14px">a) scaling limited range to full range with dithering applied when you need to output fullrange</div><div style="font-size:14px">b) already having limited range and outputting that without any further touching by the driver</div><div style="font-size:14px"><br></div><div style="font-size:14px">Use case a) is already possible. Usecase b) will be possible with the attached patch. It is a possibility to get Limited Range on screen in perfect quality in 2k15.</div><div style="font-size:14px"><br></div><div style="font-size:14px">For the future a userspace api to provide info frames and so on in a generic way should be considered but until we have this I bet we have 2 years to go. This solution also works on X11 (without wayland) and is useful for existing applications.</div><div style="font-size:14px"><br></div><div style="font-size:14px">Thanks much for consideration.</div><div style="font-size:14px"><br></div><div style="font-size:14px">---</div><div style="font-size:14px"><div>From deaa9d730c08aefefe3671d073d93d970bb39a31 Mon Sep 17 00:00:00 2001</div><div>From: fritsch <<a href="mailto:peter.fruehberger@gmail.com" target="_blank">peter.fruehberger@gmail.com</a>></div><div>Date: Sun, 29 Nov 2015 16:38:14 +0100</div><div>Subject: [PATCH] Intel: Implement Video Color Range</div><div><br></div><div>---</div><div> drivers/gpu/drm/i915/i915_drv.h      |  1 +</div><div> drivers/gpu/drm/i915/intel_display.c |  4 ++--</div><div> drivers/gpu/drm/i915/intel_drv.h     |  8 ++++++++</div><div> drivers/gpu/drm/i915/intel_hdmi.c    | 17 +++++++++++++++--</div><div> drivers/gpu/drm/i915/intel_modes.c   |  1 +</div><div> 5 files changed, 27 insertions(+), 4 deletions(-)</div><div><br></div><div>diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h</div><div>index 95bb27d..e453461 100644</div><div>--- a/drivers/gpu/drm/i915/i915_drv.h</div><div>+++ b/drivers/gpu/drm/i915/i915_drv.h</div><div>@@ -3449,6 +3449,7 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);</div><div> #define INTEL_BROADCAST_RGB_AUTO 0</div><div> #define INTEL_BROADCAST_RGB_FULL 1</div><div> #define INTEL_BROADCAST_RGB_LIMITED 2</div><div>+#define INTEL_BROADCAST_RGB_VIDEO 3</div><div> </div><div> static inline uint32_t i915_vgacntrl_reg(struct drm_device *dev)</div><div> {</div><div>diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c</div><div>index 71860f8..ea40d81 100644</div><div>--- a/drivers/gpu/drm/i915/intel_display.c</div><div>+++ b/drivers/gpu/drm/i915/intel_display.c</div><div>@@ -8605,7 +8605,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc)</div><div> <span style="white-space:pre-wrap">        </span> * consideration.</div><div> <span style="white-space:pre-wrap">     </span> */</div><div> </div><div>-<span style="white-space:pre-wrap">   </span>if (intel_crtc->config->limited_color_range)</div><div>+<span style="white-space:pre-wrap">      </span>if (intel_crtc->config->limited_color_range && !intel_crtc->config->video_color_range)</div><div> <span style="white-space:pre-wrap">             </span>coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */</div><div> </div><div> <span style="white-space:pre-wrap">      </span>/*</div><div>@@ -8629,7 +8629,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc)</div><div> <span style="white-space:pre-wrap">   </span>if (INTEL_INFO(dev)->gen > 6) {</div><div> <span style="white-space:pre-wrap">          </span>uint16_t postoff = 0;</div><div> </div><div>-<span style="white-space:pre-wrap">          </span>if (intel_crtc->config->limited_color_range)</div><div>+<span style="white-space:pre-wrap">              </span>if (intel_crtc->config->limited_color_range && !intel_crtc->config->video_color_range)</div><div> <span style="white-space:pre-wrap">                     </span>postoff = (16 * (1 << 12) / 255) & 0x1fff;</div><div> </div><div> <span style="white-space:pre-wrap">          </span>I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);</div><div>diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h</div><div>index 0598932..6940243 100644</div><div>--- a/drivers/gpu/drm/i915/intel_drv.h</div><div>+++ b/drivers/gpu/drm/i915/intel_drv.h</div><div>@@ -372,6 +372,13 @@ struct intel_crtc_state {</div><div> <span style="white-space:pre-wrap">      </span> */</div><div> <span style="white-space:pre-wrap">   </span>bool limited_color_range;</div><div> </div><div>+<span style="white-space:pre-wrap">      </span>/*</div><div>+<span style="white-space:pre-wrap">      </span> *</div><div>+<span style="white-space:pre-wrap">     </span> * Use reduced/limited/broadcast rgb range without compressing.</div><div>+<span style="white-space:pre-wrap">        </span> *</div><div>+<span style="white-space:pre-wrap">     </span> */</div><div>+<span style="white-space:pre-wrap">    </span>bool video_color_range;</div><div>+</div><div> <span style="white-space:pre-wrap">        </span>/* DP has a bunch of special case unfortunately, so mark the pipe</div><div> <span style="white-space:pre-wrap">      </span> * accordingly. */</div><div> <span style="white-space:pre-wrap">    </span>bool has_dp_encoder;</div><div>@@ -682,6 +689,7 @@ struct intel_hdmi {</div><div> <span style="white-space:pre-wrap">     </span>int ddc_bus;</div><div> <span style="white-space:pre-wrap">   </span>bool limited_color_range;</div><div> <span style="white-space:pre-wrap">      </span>bool color_range_auto;</div><div>+<span style="white-space:pre-wrap">  </span>bool color_range_video;</div><div> <span style="white-space:pre-wrap">        </span>bool has_hdmi_sink;</div><div> <span style="white-space:pre-wrap">    </span>bool has_audio;</div><div> <span style="white-space:pre-wrap">        </span>enum hdmi_force_audio force_audio;</div><div>diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c</div><div>index 9eafa19..dc78760 100644</div><div>--- a/drivers/gpu/drm/i915/intel_hdmi.c</div><div>+++ b/drivers/gpu/drm/i915/intel_hdmi.c</div><div>@@ -464,7 +464,8 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,</div><div> <span style="white-space:pre-wrap">    </span>}</div><div> </div><div> <span style="white-space:pre-wrap">     </span>if (intel_hdmi->rgb_quant_range_selectable) {</div><div>-<span style="white-space:pre-wrap">                </span>if (intel_crtc->config->limited_color_range)</div><div>+<span style="white-space:pre-wrap">              </span>if (intel_crtc->config->limited_color_range ||</div><div>+<span style="white-space:pre-wrap">            </span>    intel_crtc->config->video_color_range)</div><div> <span style="white-space:pre-wrap">                    </span>frame.avi.quantization_range =</div><div> <span style="white-space:pre-wrap">                         </span>HDMI_QUANTIZATION_RANGE_LIMITED;</div><div> <span style="white-space:pre-wrap">               </span>else</div><div>@@ -1266,6 +1267,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,</div><div> <span style="white-space:pre-wrap">         </span>pipe_config->limited_color_range =</div><div> <span style="white-space:pre-wrap">                  </span>intel_hdmi->limited_color_range;</div><div> <span style="white-space:pre-wrap">    </span>}</div><div>+<span style="white-space:pre-wrap">       </span>if (intel_hdmi->color_range_video)</div><div>+               pipe_config->video_color_range = true;</div><div> </div><div> <span style="white-space:pre-wrap">  </span>if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) {</div><div> <span style="white-space:pre-wrap">              </span>pipe_config->pixel_multiplier = 2;</div><div>@@ -1485,25 +1488,35 @@ intel_hdmi_set_property(struct drm_connector *connector,</div><div> <span style="white-space:pre-wrap">   </span>if (property == dev_priv->broadcast_rgb_property) {</div><div> <span style="white-space:pre-wrap">         </span>bool old_auto = intel_hdmi->color_range_auto;</div><div> <span style="white-space:pre-wrap">               </span>bool old_range = intel_hdmi->limited_color_range;</div><div>+<span style="white-space:pre-wrap">            </span>bool old_range_video = intel_hdmi->color_range_video;</div><div> </div><div> <span style="white-space:pre-wrap">              </span>switch (val) {</div><div> <span style="white-space:pre-wrap">         </span>case INTEL_BROADCAST_RGB_AUTO:</div><div> <span style="white-space:pre-wrap">                 </span>intel_hdmi->color_range_auto = true;</div><div>+<span style="white-space:pre-wrap">                 </span>intel_hdmi->color_range_video = false;</div><div> <span style="white-space:pre-wrap">                      </span>break;</div><div> <span style="white-space:pre-wrap">         </span>case INTEL_BROADCAST_RGB_FULL:</div><div> <span style="white-space:pre-wrap">                 </span>intel_hdmi->color_range_auto = false;</div><div> <span style="white-space:pre-wrap">                       </span>intel_hdmi->limited_color_range = false;</div><div>+<span style="white-space:pre-wrap">                     </span>intel_hdmi->color_range_video = false;</div><div> <span style="white-space:pre-wrap">                      </span>break;</div><div> <span style="white-space:pre-wrap">         </span>case INTEL_BROADCAST_RGB_LIMITED:</div><div> <span style="white-space:pre-wrap">                      </span>intel_hdmi->color_range_auto = false;</div><div> <span style="white-space:pre-wrap">                       </span>intel_hdmi->limited_color_range = true;</div><div>+<span style="white-space:pre-wrap">                      </span>intel_hdmi->color_range_video = false;</div><div>+<span style="white-space:pre-wrap">                       </span>break;</div><div>+<span style="white-space:pre-wrap">          </span>case INTEL_BROADCAST_RGB_VIDEO:</div><div>+                        intel_hdmi->color_range_auto = false;</div><div>+                        intel_hdmi->limited_color_range = true;</div><div>+                        intel_hdmi->color_range_video = true;</div><div> <span style="white-space:pre-wrap">                  </span>break;</div><div> <span style="white-space:pre-wrap">         </span>default:</div><div> <span style="white-space:pre-wrap">                       </span>return -EINVAL;</div><div> <span style="white-space:pre-wrap">                </span>}</div><div> </div><div> <span style="white-space:pre-wrap">             </span>if (old_auto == intel_hdmi->color_range_auto &&</div><div>-<span style="white-space:pre-wrap">              </span>    old_range == intel_hdmi->limited_color_range)</div><div>+<span style="white-space:pre-wrap">         </span>    old_range == intel_hdmi->limited_color_range &&</div><div>+<span style="white-space:pre-wrap">               </span>    old_range_video == intel_hdmi->color_range_video)</div><div> <span style="white-space:pre-wrap">                    </span>return 0;</div><div> </div><div> <span style="white-space:pre-wrap">             </span>goto done;</div><div>diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c</div><div>index 38a4c8c..c49681a 100644</div><div>--- a/drivers/gpu/drm/i915/intel_modes.c</div><div>+++ b/drivers/gpu/drm/i915/intel_modes.c</div><div>@@ -103,6 +103,7 @@ static const struct drm_prop_enum_list broadcast_rgb_names[] = {</div><div> <span style="white-space:pre-wrap">     </span>{ INTEL_BROADCAST_RGB_AUTO, "Automatic" },</div><div> <span style="white-space:pre-wrap">   </span>{ INTEL_BROADCAST_RGB_FULL, "Full" },</div><div> <span style="white-space:pre-wrap">        </span>{ INTEL_BROADCAST_RGB_LIMITED, "Limited 16:235" },</div><div>+<span style="white-space:pre-wrap">    </span>{ INTEL_BROADCAST_RGB_VIDEO, "Video 16:235 pass-through" },</div><div> };</div><div> </div><div> void</div><div class=""><div id=":b2" class="" tabindex="0"><img class="" src="https://ssl.gstatic.com/ui/v1/icons/mail/images/cleardot.gif"></div></div><span class=""><font color="#888888"><div>-- </div><div>2.5.0</div></font></span></div></div>