[PATCH xf86-video-amdgpu 2/7] Initialize color properties on CRTC during CRTC init

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: "Leo (Sunpeng) Li" <sunpeng.li@xxxxxxx>

And destroy them on the CRTC destroy hook.

When initializing color management properties on the private
drmmode_crtc, we want to:

1. Obtain its degamma and regamma LUT sizes
2. Default its color transform matrix (CTM) to identity
3. Program hardware with default color management values (SRGB for
   de/regamma, identity for CTM)

It's possible that cm initialization fails due to memory error or DRM
error. In which case, DDX support for color management will be disabled
on this CRTC.

Signed-off-by: Leo (Sunpeng) Li <sunpeng.li at amd.com>
---
 src/drmmode_display.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/drmmode_display.h |   8 +++
 2 files changed, 196 insertions(+), 1 deletion(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 36b22ad..de09361 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -768,6 +768,88 @@ static enum drmmode_cm_prop get_cm_enum_from_str(const char *prop_name)
 	return CM_INVALID_PROP;
 }
 
+/**
+ * Return TRUE if the given CRTC supports non-legacy color management. False
+ * otherwise.
+ */
+static Bool drmmode_crtc_cm_enabled(drmmode_crtc_private_ptr drmmode_crtc)
+{
+	return drmmode_crtc->gamma_lut_size > 0 &&
+	       drmmode_crtc->degamma_lut_size > 0;
+}
+
+/**
+ * Push staged color management properties on the CRTC to DRM.
+ *
+ * @crtc: The CRTC containing staged properties
+ * @cm_prop_index: The color property to push
+ *
+ * Return 0 on success, X-defined error codes on failure.
+ */
+static int drmmode_crtc_push_cm_prop(xf86CrtcPtr crtc,
+				     enum drmmode_cm_prop cm_prop_index)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
+	uint32_t created_blob_id = 0;
+	uint32_t drm_prop_id;
+	size_t expected_bytes = 0;
+	void *blob_data = NULL;
+	int ret;
+
+	if (!drmmode_crtc_cm_enabled(drmmode_crtc))
+		return BadName;
+
+	if (cm_prop_index == CM_GAMMA_LUT) {
+		/* Calculate the expected size of value in bytes */
+		expected_bytes = sizeof(struct drm_color_lut) *
+					drmmode_crtc->gamma_lut_size;
+		blob_data = drmmode_crtc->gamma_lut;
+	} else if (cm_prop_index == CM_DEGAMMA_LUT) {
+		expected_bytes = sizeof(struct drm_color_lut) *
+					drmmode_crtc->degamma_lut_size;
+		blob_data = drmmode_crtc->degamma_lut;
+	} else if (cm_prop_index == CM_CTM) {
+		expected_bytes = sizeof(struct drm_color_ctm);
+		blob_data = drmmode_crtc->ctm;
+	} else
+		return BadName;
+
+	if (blob_data) {
+		ret = drmModeCreatePropertyBlob(pAMDGPUEnt->fd,
+						blob_data, expected_bytes,
+						&created_blob_id);
+		if (ret) {
+			xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+				   "Creating DRM blob failed with errno %d\n",
+				   ret);
+			return BadRequest;
+		}
+	}
+
+	drm_prop_id = drmmode_crtc->drmmode->cm_prop_ids[cm_prop_index];
+	ret = drmModeObjectSetProperty(pAMDGPUEnt->fd,
+				       drmmode_crtc->mode_crtc->crtc_id,
+				       DRM_MODE_OBJECT_CRTC,
+				       drm_prop_id,
+				       (uint64_t)created_blob_id);
+
+	/* If successful, kernel will have a reference already. Safe to destroy
+	 * the blob either way.
+	 */
+	if (blob_data)
+		drmModeDestroyPropertyBlob(pAMDGPUEnt->fd, created_blob_id);
+
+	if (ret) {
+		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+			   "Setting DRM property blob failed with errno %d\n",
+			   ret);
+		return BadRequest;
+	}
+
+	return Success;
+}
+
 static void
 drmmode_crtc_gamma_do_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
 			  uint16_t *blue, int size)
@@ -1314,6 +1396,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,
@@ -1330,7 +1428,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,
 };
 
@@ -1354,6 +1452,93 @@ void drmmode_crtc_hw_id(xf86CrtcPtr crtc)
 		drmmode_crtc->hw_id = -1;
 }
 
+/**
+ * Initialize color management properties for the given CRTC by fetching its
+ * gamma/degamma LUT sizes, then programming default gamma/degamma LUTs and
+ * CTM.
+ *
+ * If the CRTC does not support color management, or if errors occur during
+ * initialization, all color properties on the driver-private CRTC will left
+ * as NULL.
+ *
+ * @drm_fd: DRM file descriptor
+ * @crtc: CRTC to initialize color management on.
+ */
+static void drmmode_crtc_cm_init(int drm_fd, xf86CrtcPtr crtc)
+{
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	drmModeObjectPropertiesPtr drm_props;
+	drmModePropertyPtr drm_prop;
+	enum drmmode_cm_prop prop_id;
+	int i;
+
+	drm_props = drmModeObjectGetProperties(drm_fd,
+					       drmmode_crtc->mode_crtc->crtc_id,
+					       DRM_MODE_OBJECT_CRTC);
+	if (!drm_props)
+		goto err_allocs;
+
+	/* Fetch degamma/gamma LUT sizes */
+	for (i = 0; i < drm_props->count_props; i++) {
+		drm_prop = drmModeGetProperty(drm_fd, drm_props->props[i]);
+		if (!drm_prop){
+			drmModeFreeObjectProperties(drm_props);
+			goto err_allocs;
+		}
+
+		prop_id = get_cm_enum_from_str(drm_prop->name);
+
+		if (prop_id == CM_GAMMA_LUT_SIZE)
+			drmmode_crtc->gamma_lut_size = drm_props->prop_values[i];
+		else if (prop_id == CM_DEGAMMA_LUT_SIZE)
+			drmmode_crtc->degamma_lut_size = drm_props->prop_values[i];
+
+		drmModeFreeProperty(drm_prop);
+	}
+	drmModeFreeObjectProperties(drm_props);
+
+	if (!drmmode_crtc_cm_enabled(drmmode_crtc)) {
+		xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
+			   "CRTC%d does not support non-legacy color management.\n",
+			   drmmode_get_crtc_id(crtc));
+		drmmode_crtc->degamma_lut_size = 0;
+		drmmode_crtc->gamma_lut_size = 0;
+		return;
+	}
+	xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
+		   "CRTC%d supports non-legacy color management.\n",
+		   drmmode_get_crtc_id(crtc));
+
+	/* Init CTM to identity. Values are in S31.32 fixed-point format */
+	drmmode_crtc->ctm = calloc(1, sizeof(*drmmode_crtc->ctm));
+	if (drmmode_crtc->ctm == NULL)
+		goto err_allocs;
+
+	drmmode_crtc->ctm->matrix[0] = drmmode_crtc->ctm->matrix[4] =
+		drmmode_crtc->ctm->matrix[8] = (uint64_t)1 << 32;
+
+	/* Push properties to reset properties currently in hardware */
+	for (i = 0; i < CM_NUM_PROPS; i++) {
+		if (i == CM_DEGAMMA_LUT_SIZE || i == CM_GAMMA_LUT_SIZE)
+			continue;
+
+		if (drmmode_crtc_push_cm_prop(crtc, i))
+			xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+				   "Failed to initialize color management "
+				   "property %s on CRTC%d. Property value may "
+				   "not reflect actual hardware state.\n",
+				   cm_prop_names[i],
+				   drmmode_get_crtc_id(crtc));
+	}
+
+	return;
+
+err_allocs:
+	xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+		   "Memory error initializing cm properties for CRTC%d",
+		   drmmode_get_crtc_id(crtc));
+}
+
 static unsigned int
 drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
 {
@@ -1374,6 +1559,8 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
 	crtc->driver_private = drmmode_crtc;
 	drmmode_crtc_hw_id(crtc);
 
+	drmmode_crtc_cm_init(pAMDGPUEnt->fd, crtc);
+
 	/* 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 bbb5423..1293249 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -128,6 +128,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



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux