[PATCH xf86-video-amdgpu 3/5] Keep CRTC properties consistent

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

 



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

In cases where CRTC properties are updated without going through
RRChangeOutputProperty, we don't update the properties in user land.

Consider setting legacy gamma. It doesn't go through
RRChangeOutputProperty, but modifies the CRTC's color management
properties. Unless they are updated, the user properties will remain
stale.

Therefore, add a function to update user CRTC properties by querying DRM,
and call it whenever legacy gamma is changed.

Also modify the configure and change helper to take in a 'pending'
argument, to allow property updates for user only.

Signed-off-by: Leo (Sunpeng) Li <sunpeng.li at amd.com>
---
 src/drmmode_display.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 98 insertions(+), 4 deletions(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 1966fd2..45457c4 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -61,8 +61,13 @@
 
 #define DEFAULT_NOMINAL_FRAME_RATE 60
 
+/* Forward declarations */
+
 static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height);
 
+static void drmmode_crtc_update_resources(xf86CrtcPtr crtc);
+
+
 static Bool
 AMDGPUZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name)
 {
@@ -768,6 +773,7 @@ drmmode_crtc_gamma_do_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
 
 	drmModeCrtcSetGamma(pAMDGPUEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
 			    size, red, green, blue);
+	drmmode_crtc_update_resources(crtc);
 }
 
 Bool
@@ -1653,10 +1659,15 @@ static Bool drmmode_property_ignore(drmModePropertyPtr prop)
 * Configure and change the given output property through randr. Currently
 * ignores DRM_MODE_PROP_ENU property types. Used as part of create_resources.
 *
+* @output: The output to configure and change the property on.
+* @pmode_prop: The driver-private property object.
+* @pending: Whether the property changes are pending.
+*
 * Return: 0 on success, X-defined error codes on failure.
 */
 static int __rr_configure_and_change_property(xf86OutputPtr output,
-					      drmmode_prop_ptr pmode_prop)
+					      drmmode_prop_ptr pmode_prop,
+					      Bool pending)
 {
 	drmModePropertyPtr mode_prop = pmode_prop->mode_prop;
 	Bool is_immutable = mode_prop->flags & DRM_MODE_PROP_IMMUTABLE ?
@@ -1689,7 +1700,7 @@ static int __rr_configure_and_change_property(xf86OutputPtr output,
 					     pmode_prop->atoms[0],
 					     XA_INTEGER, 32,
 					     PropModeReplace, 1, &blob_id,
-					     FALSE, TRUE);
+					     FALSE, pending);
 		if (err)
 			goto rrchange_error;
 	}
@@ -1718,7 +1729,7 @@ static int __rr_configure_and_change_property(xf86OutputPtr output,
 					     pmode_prop->atoms[0],
 					     XA_INTEGER, 32,
 					     PropModeReplace, 1, &value,
-					     FALSE, TRUE);
+					     FALSE, pending);
 		if (err)
 			goto rrchange_error;
 	}
@@ -1739,6 +1750,89 @@ rrchange_error:
 
 }
 
+
+/**
+ * Update user properties on the given CRTC with values from DRM.
+ *
+ * This should be called when a CRTC property is set, without going through
+ * RRChangeOutputProperty.
+ *
+ * For example, setting legacy gamma will modify color management CRTC
+ * properties, but it does not go through RRChangeOutputProperty. This leaves
+ * the user property values in a stale state. Calling this function will grab
+ * updated values from DRM, and update the user properties.
+ */
+static void drmmode_crtc_update_resources(xf86CrtcPtr crtc)
+{
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
+	xf86CrtcConfigPtr xf86_crtc_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+	int i;
+
+	drmmode_crtc_private_ptr user_crtc = crtc->driver_private;
+
+	/* Get list of DRM CRTC properties, and their values */
+	drmModeObjectPropertiesPtr drm_props;
+	drm_props = drmModeObjectGetProperties(pAMDGPUEnt->fd,
+					       user_crtc->mode_crtc->crtc_id,
+					       DRM_MODE_OBJECT_CRTC);
+	if (!drm_props)
+		goto err_allocs;
+
+	for (i = 0; i < drm_props->count_props; i++) {
+		drmmode_prop_ptr user_prop = NULL;
+		drmModePropertyPtr drm_prop;
+		int j;
+
+		drm_prop = drmModeGetProperty(pAMDGPUEnt->fd,
+					       drm_props->props[i]);
+		if (!drm_prop)
+			goto err_allocs;
+
+		/* Check if property is currently on user CRTC */
+		for (j = 0; j < user_crtc->num_props; j++) {
+			user_prop = &user_crtc->props[j];
+
+			if (!strcmp(drm_prop->name,
+				    user_prop->mode_prop->name))
+				/* Found */
+				break;
+		}
+		if (j == user_crtc->num_props) {
+			/* Not found */
+			drmModeFreeProperty(drm_prop);
+			continue;
+		}
+
+		/* If found, update it with value from kernel */
+		drmModeFreeProperty(user_prop->mode_prop);
+		user_prop->mode_prop = drm_prop;
+		user_prop->value = drm_props->prop_values[i];
+
+		for (j = 0; j < xf86_crtc_config->num_output; j++) {
+			xf86OutputPtr output = xf86_crtc_config->output[j];
+			if (output->crtc != crtc)
+				continue;
+
+			/* Non-pending configure and change: Just updating
+			 * values on user-side */
+			__rr_configure_and_change_property(output,
+							   user_prop,
+							   FALSE);
+		}
+	}
+
+	drmModeFreeObjectProperties(drm_props);
+	return;
+
+err_allocs:
+	xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+		   "Memory error updating resources for CRTC %d\n",
+		   user_crtc->mode_crtc->crtc_id);
+	drmModeFreeObjectProperties(drm_props);
+	return;
+
+}
+
 static void drmmode_crtc_create_resources(xf86CrtcPtr crtc,
 					  xf86OutputPtr output)
 {
@@ -1792,7 +1886,7 @@ static void drmmode_crtc_create_resources(xf86CrtcPtr crtc,
 	/* Finally, configure and set the properties */
 	for (i = 0; i < pmode_crtc->num_props; i++) {
 		pmode_prop = &pmode_crtc->props[i];
-		__rr_configure_and_change_property(output, pmode_prop);
+		__rr_configure_and_change_property(output, pmode_prop, TRUE);
 	}
 
 	drmModeFreeObjectProperties(mode_props);
-- 
2.7.4



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

  Powered by Linux