From: "Leo (Sunpeng) Li" <sunpeng.li@xxxxxxx> Non-legacy color management consists of 3 properties on the CRTC: Degamma LUT, Color Transformation Matrix (CTM), and Gamma LUT. Add these properties to the driver-private CRTC, and initialize them when the CRTC is initialized. These values are refered to as "staged" values. They exist in the DDX driver, but require a "push" to DRM in order to be realized in hardware. Also add a destructor for the driver-private CRTC, which cleans up the non-legacy properties. Signed-off-by: Leo (Sunpeng) Li <sunpeng.li at amd.com> --- src/drmmode_display.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++- src/drmmode_display.h | 8 ++++ 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 49284c6..0ffc6ad 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -747,6 +747,83 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, } } +enum drmmode_cm_prop { + CM_GAMMA_LUT_SIZE, + CM_DEGAMMA_LUT_SIZE, + CM_GAMMA_LUT, + CM_CTM, + CM_DEGAMMA_LUT, + CM_NUM_PROPS, + CM_INVALID_PROP = -1, +}; + +char *CM_PROP_NAMES[] = { + "GAMMA_LUT_SIZE", + "DEGAMMA_LUT_SIZE", + "GAMMA_LUT", + "CTM", + "DEGAMMA_LUT", +}; + +/** + * Return the enum of the color management property with the given name. + */ +static enum drmmode_cm_prop get_cm_enum_from_str(const char *prop_name) +{ + enum drmmode_cm_prop ret; + + for (ret = 0; ret < CM_NUM_PROPS; ret++) { + if (!strcmp(prop_name, CM_PROP_NAMES[ret])) + return ret; + } + return CM_INVALID_PROP; +} + +/** + * Query DRM for the property value of the specified color management property, + * on the specified CRTC. + * + * @crtc: The CRTC to query DRM properties on. + * @prop_id: Color management property enum. + * Return: The property value (if property is DRM blob, return blob_id) of the + * specified color property. 0 if property not found. + */ +static uint64_t get_drm_cm_prop_value(xf86CrtcPtr crtc, + enum drmmode_cm_prop prop_id) +{ + AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmModeObjectPropertiesPtr drm_props; + int i; + + /* Get list of DRM CRTC properties, and their values */ + drm_props = drmModeObjectGetProperties(pAMDGPUEnt->fd, + drmmode_crtc->mode_crtc->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (!drm_props) + goto err_allocs; + + for (i = 0; i < drm_props->count_props; i++) { + drmModePropertyPtr drm_prop; + + drm_prop = drmModeGetProperty(pAMDGPUEnt->fd, + drm_props->props[i]); + if (!drm_prop) + goto err_allocs; + + if (get_cm_enum_from_str(drm_prop->name) == prop_id){ + drmModeFreeProperty(drm_prop); + return drm_props->prop_values[i]; + } + + drmModeFreeProperty(drm_prop); + } + +err_allocs: + drmModeFreeObjectProperties(drm_props); + return 0; +} + static void drmmode_crtc_gamma_do_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, uint16_t *blue, int size) @@ -1293,6 +1370,22 @@ static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) return TRUE; } +static void drmmode_crtc_destroy(xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + drmModeFreeCrtc(drmmode_crtc->mode_crtc); + + /* Free LUTs and CTM */ + free(drmmode_crtc->gamma_lut); + free(drmmode_crtc->degamma_lut); + free(drmmode_crtc->ctm); + + free(drmmode_crtc); + crtc->driver_private = NULL; +} + + static xf86CrtcFuncsRec drmmode_crtc_funcs = { .dpms = drmmode_crtc_dpms, .set_mode_major = drmmode_set_mode_major, @@ -1309,7 +1402,7 @@ static xf86CrtcFuncsRec drmmode_crtc_funcs = { .shadow_create = drmmode_crtc_shadow_create, .shadow_allocate = drmmode_crtc_shadow_allocate, .shadow_destroy = drmmode_crtc_shadow_destroy, - .destroy = NULL, /* XXX */ + .destroy = drmmode_crtc_destroy, .set_scanout_pixmap = drmmode_set_scanout_pixmap, }; @@ -1353,6 +1446,18 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res crtc->driver_private = drmmode_crtc; drmmode_crtc_hw_id(crtc); + drmmode_crtc->gamma_lut_size = + (uint32_t)get_drm_cm_prop_value(crtc, CM_GAMMA_LUT_SIZE); + drmmode_crtc->degamma_lut_size = + (uint32_t)get_drm_cm_prop_value(crtc, CM_DEGAMMA_LUT_SIZE); + drmmode_crtc->ctm = calloc(1, sizeof(*drmmode_crtc->ctm)); + if (drmmode_crtc->ctm == NULL) + return 0; + + /* Init to identity matrix. Values are in S31.32 fixed-point format */ + drmmode_crtc->ctm->matrix[0] = drmmode_crtc->ctm->matrix[4] = + drmmode_crtc->ctm->matrix[8] = (uint64_t)1 << 32; + /* Mark num'th crtc as in use on this device. */ pAMDGPUEnt->assigned_crtcs |= (1 << num); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 25ae9f8..21498e3 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -109,6 +109,14 @@ typedef struct { unsigned present_vblank_msc; Bool present_flip_expected; #endif + + uint32_t gamma_lut_size; + struct drm_color_lut *gamma_lut; + + uint32_t degamma_lut_size; + struct drm_color_lut *degamma_lut; + + struct drm_color_ctm *ctm; } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; typedef struct { -- 2.7.4