From: "Leo (Sunpeng) Li" <sunpeng.li@xxxxxxx> The properties on an RandR output needs to stay consistent throughout it's lifecycle. However, we cannot list color properties on an output if there is no CRTC attached. Therefore, create a fake CRTC, and initialize "disabled" color properites on outputs without a CRTC. Signed-off-by: Leo (Sunpeng) Li <sunpeng.li at amd.com> --- src/drmmode_display.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 85de01e..c28796c 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -869,6 +869,124 @@ err_allocs: } /** + * 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. If the request is pending, then the change will make it's way into + * the kernel DRM driver. Otherwise, the request will be a user-land only + * update. + * + * @output: RandR output to set the property on. + * @crtc: The driver-private CRTC object containing the color properties. + * @cm_prop_index: Color management property to configure and change. + * @pending: Whether this request is pending. + * + * 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 pending) +{ + Bool need_configure = TRUE; + unsigned long length = 0; + void *data = NULL; + int format = 0; + uint16_t value; + 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->gamma_lut_size; + range[0] = 0; + range[1] = -1; + + } else if (cm_prop_index == CM_DEGAMMA_LUT_SIZE) { + format = 32; + length = 1; + data = &crtc->degamma_lut_size; + 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->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; + value = 0; + data = &value; + } + } 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->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; + value = 0; + data = &value; + } + } else { + /* CTM is fixed-point S31.32 format. */ + format = 16; + need_configure = FALSE; + if (crtc->ctm) { + length = sizeof(*crtc->ctm) >> 1; + data = crtc->ctm; + } else { + length = 1; + value = 0; + data = &value; + } + } + + 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; + } + } + + err = RRChangeOutputProperty(output->randr_output, atom, + XA_INTEGER, format, + PropModeReplace, + length, data, FALSE, pending); + 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 @@ -1851,6 +1969,40 @@ static Bool drmmode_property_ignore(drmModePropertyPtr prop) return FALSE; } +/** + * Using a fake CRTC, configure and change color properties for the output, + * using the default (0) color properties on the fake CRTC. Use to initialize + * color management properties on an output where a CRTC has not yet been + * attached. + */ +static void drmmode_disabled_crtc_create_resources(xf86OutputPtr output) +{ + drmmode_crtc_private_ptr fake_crtc; + int i, ret; + + /* Create a fake crtc */ + fake_crtc = calloc(1, sizeof(drmmode_crtc_private_rec)); + if (!fake_crtc) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "Memory error creating resources for fake CRTC\n"); + return; + } + + for (i = 0; i < CM_NUM_PROPS; i++) { + ret = rr_configure_and_change_cm_property(output, fake_crtc, i, + FALSE); + if (ret) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "Configur and change cm property error %d\n", + ret); + break; + } + } + + free(fake_crtc); + return; +} + static void drmmode_output_create_resources(xf86OutputPtr output) { AMDGPUInfoPtr info = AMDGPUPTR(output->scrn); @@ -1978,6 +2130,8 @@ static void drmmode_output_create_resources(xf86OutputPtr output) } } } + + drmmode_disabled_crtc_create_resources(output); } static void -- 2.7.4