From: "Leo (Sunpeng) Li" <[email protected]>

And destroy them on the CRTC destroy hook.

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

1. Default its color transform matrix (CTM) to identity
2. 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, the RandR state may not reflect the actual
hardware state.

v2:
- Use switch statement in push_cm_prop
- Get rid of per-CRTC cm support checks. Keep it simple and only check
  the first CRTC, since kernel will always report all or nothing for AMD
  hardware.
- Remove per-CRTC LUT size caching, drmmode now holds that. Update
  commit message to reflect this.

Signed-off-by: Leo (Sunpeng) Li <[email protected]>
---
 src/drmmode_display.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/drmmode_display.h |   3 ++
 2 files changed, 149 insertions(+), 1 deletion(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 994f130..d750410 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -768,6 +768,89 @@ static enum drmmode_cm_prop get_cm_enum_from_str(const 
char *prop_name)
        return CM_INVALID_PROP;
 }
 
+/**
+ * Return TRUE if kernel supports non-legacy color management.
+ */
+static Bool drmmode_cm_enabled(drmmode_ptr drmmode)
+{
+       return drmmode->cm_prop_ids[CM_GAMMA_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);
+       drmmode_ptr drmmode = drmmode_crtc->drmmode;
+       uint32_t created_blob_id = 0;
+       uint32_t drm_prop_id;
+       size_t expected_bytes = 0;
+       void *blob_data = NULL;
+       int ret;
+
+       switch (cm_prop_index) {
+       case CM_GAMMA_LUT:
+               /* Calculate the expected size of value in bytes */
+               expected_bytes = sizeof(struct drm_color_lut) *
+                                       drmmode->gamma_lut_size;
+               blob_data = drmmode_crtc->gamma_lut;
+               break;
+       case CM_DEGAMMA_LUT:
+               expected_bytes = sizeof(struct drm_color_lut) *
+                                       drmmode->degamma_lut_size;
+               blob_data = drmmode_crtc->degamma_lut;
+               break;
+       case CM_CTM:
+               expected_bytes = sizeof(struct drm_color_ctm);
+               blob_data = drmmode_crtc->ctm;
+               break;
+       default:
+               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 +1397,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 +1429,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 +1453,50 @@ void drmmode_crtc_hw_id(xf86CrtcPtr crtc)
                drmmode_crtc->hw_id = -1;
 }
 
+/**
+ * Initialize color management properties for the given CRTC by programming
+ * the 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;
+       drmmode_ptr drmmode = drmmode_crtc->drmmode;
+       int i;
+
+       if (!drmmode_cm_enabled(drmmode))
+               return;
+
+       /* 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) {
+               xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+                          "Memory error initializing CTM for CRTC%d",
+                          drmmode_get_crtc_id(crtc));
+               return;
+       }
+
+       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_DEGAMMA_LUT_SIZE; i++) {
+               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));
+       }
+}
+
 static unsigned int
 drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr 
mode_res, int num)
 {
@@ -1374,6 +1517,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 4aa8e88..0f0227c 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -131,6 +131,9 @@ typedef struct {
        unsigned present_vblank_msc;
        Bool present_flip_expected;
 #endif
+       struct drm_color_lut *degamma_lut;
+       struct drm_color_ctm *ctm;
+       struct drm_color_lut *gamma_lut;
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
 
 typedef struct {
-- 
2.7.4

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to