From: "Leo (Sunpeng) Li" <sunpeng.li@xxxxxxx> List color management properties on outputs if there's at least one CRTC that supports color management. Otherwise, don't list them at all. If there's no CRTC attached to the output, and there exists a CRTC that supports color management, then list "disabled" properties (immutable and NULL-valued). Signed-off-by: Leo (Sunpeng) Li <sunpeng.li at amd.com> --- src/drmmode_display.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index de09361..32ac441 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -769,6 +769,15 @@ static enum drmmode_cm_prop get_cm_enum_from_str(const char *prop_name) } /** + * Return TRUE if there's at least one CRTC that supports non-legacy color + * management. False otherwise. + */ +static Bool drmmode_cm_enabled(drmmode_ptr drmmode) +{ + return drmmode->cm_prop_ids[CM_GAMMA_LUT_SIZE] != 0; +} + +/** * Return TRUE if the given CRTC supports non-legacy color management. False * otherwise. */ @@ -779,6 +788,123 @@ static Bool drmmode_crtc_cm_enabled(drmmode_crtc_private_ptr drmmode_crtc) } /** + * Configure and change a color property on a CRTC, through RandR. Only the + * specified output will be affected, even if the CRTC is attached to multiple + * outputs. Note that changes will be non-pending: the changes won't be pushed + * to kernel driver. + * + * @output: RandR output to set the property on. + * @crtc: The driver-private CRTC object containing the color properties. + * If this is NULL, "disabled" values of 0 will be used. + * @cm_prop_index: Color management property to configure and change. + * + * Return 0 on success, X-defined error code otherwise. + */ +static int rr_configure_and_change_cm_property(xf86OutputPtr output, + drmmode_crtc_private_ptr crtc, + enum drmmode_cm_prop cm_prop_index) +{ + Bool need_configure = TRUE; + unsigned long length = 0; + void *data = NULL; + int format = 0; + uint32_t zero = 0; + INT32 range[2]; + Atom atom; + int err; + + if (cm_prop_index == CM_INVALID_PROP) + return BadName; + + atom = MakeAtom(cm_prop_names[cm_prop_index], + strlen(cm_prop_names[cm_prop_index]), + TRUE); + if (!atom) + return BadAlloc; + + if (cm_prop_index == CM_GAMMA_LUT_SIZE) { + format = 32; + length = 1; + data = crtc ? &crtc->gamma_lut_size : &zero; + range[0] = 0; + range[1] = -1; + + } else if (cm_prop_index == CM_DEGAMMA_LUT_SIZE) { + format = 32; + length = 1; + data = crtc ? &crtc->degamma_lut_size : &zero; + range[0] = 0; + range[1] = -1; + + } else if (cm_prop_index == CM_GAMMA_LUT) { + format = 16; + range[0] = 0; + range[1] = (1 << 16) - 1; // Max 16 bit unsigned int. + if (crtc && crtc->gamma_lut) { + /* Convert from 8bit size to 16bit size */ + length = sizeof(*crtc->gamma_lut) >> 1; + length *= crtc->gamma_lut_size; + data = crtc->gamma_lut; + } else { + length = 1; + data = &zero; + } + } else if (cm_prop_index == CM_DEGAMMA_LUT) { + format = 16; + range[0] = 0; + range[1] = (1 << 16) - 1; // Max 16 bit unsigned int. + if (crtc && crtc->degamma_lut) { + /* Convert from 8bit size to 16bit size */ + length = sizeof(*crtc->degamma_lut) >> 1; + length *= crtc->degamma_lut_size; + data = crtc->degamma_lut; + } else { + length = 1; + data = &zero; + } + } else { + /* CTM is fixed-point S31.32 format. */ + format = 32; + need_configure = FALSE; + if (crtc && crtc->ctm) { + /* Convert from 8bit size to 32bit size */ + length = sizeof(*crtc->ctm) >> 2; + data = crtc->ctm; + } else { + length = 1; + data = &zero; + } + } + + if (need_configure) { + err = RRConfigureOutputProperty(output->randr_output, atom, + FALSE, TRUE, FALSE, 2, range); + if (err) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "Configuring color management property %s failed with %d\n", + cm_prop_names[cm_prop_index], err); + return err; + } + } + + /* Always issue a non-pending change. We'll push cm properties + * ourselves. + */ + err = RRChangeOutputProperty(output->randr_output, atom, + XA_INTEGER, format, + PropModeReplace, + length, data, FALSE, FALSE); + if (err) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "Changing color management property %s failed with %d\n", + cm_prop_names[cm_prop_index], err); + return err; + } + + return 0; +} + +/** * Push staged color management properties on the CRTC to DRM. * * @crtc: The CRTC containing staged properties @@ -1822,6 +1948,7 @@ static void drmmode_output_create_resources(xf86OutputPtr output) { AMDGPUInfoPtr info = AMDGPUPTR(output->scrn); drmmode_output_private_ptr drmmode_output = output->driver_private; + drmmode_crtc_private_ptr drmmode_crtc; drmModeConnectorPtr mode_output = drmmode_output->mode_output; AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(output->scrn); drmModePropertyPtr drmmode_prop, tearfree_prop; @@ -1945,6 +2072,27 @@ static void drmmode_output_create_resources(xf86OutputPtr output) } } } + + /* + * Note that we usually check for cm support per CRTC. However, since + * one may not be attached to the output at the moment, we will check + * if there's at least one CRTC that supports cm. + * + * This means that if no CRTCs have cm support, then we won't list the + * cm properties on any of the outputs. + * + * But if even one CRTC has cm support, then we will list the + * properties on all outputs. Outputs with no CRTC, or with one that + * doesn't support cm, will then have "disabled" cm properties (null- + * valued, and cannot be modified). + */ + if (!drmmode_cm_enabled(drmmode_output->drmmode)) + return; + + drmmode_crtc = output->crtc ? output->crtc->driver_private : NULL; + + for (i = 0; i < CM_NUM_PROPS; i++) + rr_configure_and_change_cm_property(output, drmmode_crtc, i); } static void -- 2.7.4