From: Ville Syrjälä <ville.syrj...@linux.intel.com>

Probe the GAMMA_LUT/GAMMA_LUT_SIZE props and utilize them when
the running with > 8bpc.

v2: s/sna_crtc_id/__sna_crtc_id/ in DBG since we have a sna_crtc

Cc: Mario Kleiner <mario.kleiner...@gmail.com>
Signed-off-by: Ville Syrjälä <ville.syrj...@linux.intel.com>
---
 src/sna/sna_display.c | 245 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 207 insertions(+), 38 deletions(-)

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 41edfec12839..6d671dce8c14 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -127,6 +127,7 @@ struct local_mode_obj_get_properties {
        uint32_t obj_type;
        uint32_t pad;
 };
+#define LOCAL_MODE_OBJECT_CRTC 0xcccccccc
 #define LOCAL_MODE_OBJECT_PLANE 0xeeeeeeee
 
 struct local_mode_set_plane {
@@ -229,6 +230,11 @@ struct sna_crtc {
        } primary;
        struct list sprites;
 
+       struct drm_color_lut *gamma_lut;
+       uint64_t gamma_lut_prop;
+       uint64_t gamma_lut_blob;
+       uint32_t gamma_lut_size;
+
        uint32_t mode_serial, flip_serial;
 
        uint32_t last_seq, wrap_seq;
@@ -317,6 +323,9 @@ static void __sna_output_dpms(xf86OutputPtr output, int 
dpms, int fixup);
 static void sna_crtc_disable_cursor(struct sna *sna, struct sna_crtc *crtc);
 static bool sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc,
                          struct kgem_bo *bo, int x, int y);
+static void sna_crtc_gamma_set(xf86CrtcPtr crtc,
+                              CARD16 *red, CARD16 *green,
+                              CARD16 *blue, int size);
 
 static bool is_zaphod(ScrnInfoPtr scrn)
 {
@@ -3150,11 +3159,9 @@ sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr 
mode,
               mode->VDisplay <= sna->mode.max_crtc_height);
 
 #if HAS_GAMMA
-       drmModeCrtcSetGamma(sna->kgem.fd, __sna_crtc_id(sna_crtc),
-                           crtc->gamma_size,
-                           crtc->gamma_red,
-                           crtc->gamma_green,
-                           crtc->gamma_blue);
+       sna_crtc_gamma_set(crtc,
+                          crtc->gamma_red, crtc->gamma_green,
+                          crtc->gamma_blue, crtc->gamma_size);
 #endif
 
        saved_kmode = sna_crtc->kmode;
@@ -3212,12 +3219,44 @@ void sna_mode_adjust_frame(struct sna *sna, int x, int 
y)
 
 static void
 sna_crtc_gamma_set(xf86CrtcPtr crtc,
-                      CARD16 *red, CARD16 *green, CARD16 *blue, int size)
+                  CARD16 *red, CARD16 *green, CARD16 *blue, int size)
 {
-       assert(to_sna_crtc(crtc));
-       drmModeCrtcSetGamma(to_sna(crtc->scrn)->kgem.fd,
-                           sna_crtc_id(crtc),
-                           size, red, green, blue);
+       struct sna *sna = to_sna(crtc->scrn);
+       struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+       struct drm_color_lut *lut = sna_crtc->gamma_lut;
+       uint32_t blob_size = size * sizeof(lut[0]);
+       uint32_t blob_id;
+       int ret, i;
+
+       DBG(("%s: gamma_size %d\n", __FUNCTION__, size));
+
+       if (!lut) {
+               assert(size == 256);
+
+               drmModeCrtcSetGamma(to_sna(crtc->scrn)->kgem.fd,
+                                   sna_crtc_id(crtc),
+                                   size, red, green, blue);
+               return;
+       }
+
+       assert(size == sna_crtc->gamma_lut_size);
+
+       for (i = 0; i < size; i++) {
+               lut[i].red = red[i];
+               lut[i].green = green[i];
+               lut[i].blue = blue[i];
+       }
+
+       ret = drmModeCreatePropertyBlob(sna->kgem.fd, lut, blob_size, &blob_id);
+       if (ret)
+               return;
+
+       ret = drmModeObjectSetProperty(sna->kgem.fd,
+                                      sna_crtc->id, DRM_MODE_OBJECT_CRTC,
+                                      sna_crtc->gamma_lut_prop,
+                                      blob_id);
+
+       drmModeDestroyPropertyBlob(sna->kgem.fd, blob_id);
 }
 
 static void
@@ -3229,6 +3268,8 @@ sna_crtc_destroy(xf86CrtcPtr crtc)
        if (sna_crtc == NULL)
                return;
 
+       free(sna_crtc->gamma_lut);
+
        list_for_each_entry_safe(sprite, sn, &sna_crtc->sprites, link)
                free(sprite);
 
@@ -3663,6 +3704,55 @@ bool sna_has_sprite_format(struct sna *sna, uint32_t 
format)
        return false;
 }
 
+inline static bool prop_is_gamma_lut(const struct drm_mode_get_property *prop)
+{
+       return prop_has_type_and_name(prop, 4, "GAMMA_LUT");
+}
+
+inline static bool prop_is_gamma_lut_size(const struct drm_mode_get_property 
*prop)
+{
+       return prop_has_type_and_name(prop, 1, "GAMMA_LUT_SIZE");
+}
+
+static void sna_crtc_parse_prop(struct sna *sna,
+                               struct drm_mode_get_property *prop,
+                               uint64_t value, void *data)
+{
+       struct sna_crtc *crtc = data;
+
+       if (prop_is_gamma_lut(prop)) {
+               crtc->gamma_lut_prop = prop->prop_id;
+               crtc->gamma_lut_blob = value;
+       } else if (prop_is_gamma_lut_size(prop)) {
+               crtc->gamma_lut_size = value;
+       }
+}
+
+static void
+sna_crtc_init__props(struct sna *sna, struct sna_crtc *crtc)
+{
+       ScrnInfoPtr scrn = sna->scrn;
+
+       parse_props(sna, LOCAL_MODE_OBJECT_CRTC, crtc->id,
+                   sna_crtc_parse_prop, crtc);
+
+       /* use high precision gamma LUT for > 8bpc */
+       /* X-Server < 1.20 mishandles > 256 slots / > 8 bpc color maps. */
+       if (scrn->rgbBits <= 8 ||
+           XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,20,0,0,0))
+               crtc->gamma_lut_size = 0;
+
+       if (crtc->gamma_lut_size) {
+               crtc->gamma_lut = calloc(max(crtc->gamma_lut_size, 256),
+                                        sizeof(crtc->gamma_lut[0]));
+               if (!crtc->gamma_lut)
+                       crtc->gamma_lut_size = 0;
+       }
+
+       DBG(("%s: CRTC:%d, gamma_lut_size=%d\n", __FUNCTION__,
+            __sna_crtc_id(crtc), crtc->gamma_lut_size));
+}
+
 static void
 sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *crtc)
 {
@@ -3723,6 +3813,9 @@ sna_crtc_add(ScrnInfoPtr scrn, unsigned id)
 
        list_init(&sna_crtc->sprites);
        sna_crtc_init__rotation(sna, sna_crtc);
+
+       sna_crtc_init__props(sna, sna_crtc);
+
        sna_crtc_find_planes(sna, sna_crtc);
 
        DBG(("%s: CRTC:%d [pipe=%d], primary id=%x: supported-rotations=%x, 
current-rotation=%x\n",
@@ -7274,36 +7367,110 @@ static void output_set_gamma(xf86OutputPtr output, 
xf86CrtcPtr crtc)
                          mon->mon_gamma_blue);
 }
 
+static bool
+crtc_get_gamma_lut(xf86CrtcPtr crtc,
+                  CARD16 *red, CARD16 *green, CARD16 *blue, int size)
+{
+
+       struct sna *sna = to_sna(crtc->scrn);
+       struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+       struct drm_color_lut *lut = sna_crtc->gamma_lut;
+       struct drm_mode_get_blob blob;
+       int lut_size, i;
+
+       DBG(("%s: gamma_size %d\n", __FUNCTION__, size));
+
+       memset(&blob, 0, sizeof(blob));
+       blob.blob_id = sna_crtc->gamma_lut_blob;
+
+       if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+               return false;
+
+       lut_size = blob.length / sizeof(lut[0]);
+
+       if (lut_size == 0 ||
+           lut_size > max(sna_crtc->gamma_lut_size, 256))
+               return false;
+
+       blob.data = (uintptr_t)lut;
+
+       if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+               return false;
+
+       for (i = 0; i < size; i++) {
+               struct drm_color_lut *entry =
+                       &lut[i * (lut_size - 1) / (size - 1)];
+
+               red[i] = entry->red;
+               green[i] = entry->green;
+               blue[i] = entry->blue;
+       }
+
+       return red[size - 1] &&
+               green[size - 1] &&
+               blue[size - 1];
+}
+
+static bool crtc_get_gamma_legacy(xf86CrtcPtr crtc,
+                                 CARD16 *red,
+                                 CARD16 *green,
+                                 CARD16 *blue,
+                                 int size)
+{
+       struct sna *sna = to_sna(crtc->scrn);
+       struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
+       struct drm_mode_crtc_lut lut = {
+               .crtc_id = __sna_crtc_id(sna_crtc),
+               .gamma_size = size,
+               .red = (uintptr_t)red,
+               .green = (uintptr_t)green,
+               .blue = (uintptr_t)blue,
+       };
+
+       if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETGAMMA, &lut) != 0)
+               return false;
+
+       VG(VALGRIND_MAKE_MEM_DEFINED(red, size*sizeof(red[0])));
+       VG(VALGRIND_MAKE_MEM_DEFINED(green, size*sizeof(green[0])));
+       VG(VALGRIND_MAKE_MEM_DEFINED(bluered, size*sizeof(blue[0])));
+
+       return red[size - 1] &&
+               green[size - 1] &&
+               blue[size - 1];
+}
+
 static void crtc_init_gamma(xf86CrtcPtr crtc)
 {
+       struct sna *sna = to_sna(crtc->scrn);
+       struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
        uint16_t *gamma;
+       int size;
+
+       assert(sna_crtc);
+
+       size = sna_crtc->gamma_lut_size;
+       if (!size)
+               size = 256;
 
        /* Initialize the gamma ramps */
        gamma = NULL;
-       if (crtc->gamma_size == 256)
+       if (crtc->gamma_size == size)
                gamma = crtc->gamma_red;
        if (gamma == NULL)
-               gamma = malloc(3 * 256 * sizeof(uint16_t));
+               gamma = malloc(3 * size * sizeof(uint16_t));
        if (gamma) {
-               struct sna *sna = to_sna(crtc->scrn);
-               struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
                struct drm_mode_crtc_lut lut;
-               bool gamma_set = false;
+               bool gamma_set;
+               uint16_t *red = gamma;
+               uint16_t *green = gamma + size;
+               uint16_t *blue = gamma + 2 * size;
 
-               assert(sna_crtc);
-
-               lut.crtc_id = __sna_crtc_id(sna_crtc);
-               lut.gamma_size = 256;
-               lut.red = (uintptr_t)(gamma);
-               lut.green = (uintptr_t)(gamma + 256);
-               lut.blue = (uintptr_t)(gamma + 2 * 256);
-               if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETGAMMA, &lut) == 0) 
{
-                       VG(VALGRIND_MAKE_MEM_DEFINED(gamma, 
3*256*sizeof(gamma[0])));
-                       gamma_set =
-                               gamma[256 - 1] &&
-                               gamma[2*256 - 1] &&
-                               gamma[3*256 - 1];
-               }
+               if (sna_crtc->gamma_lut_size)
+                       gamma_set = crtc_get_gamma_lut(crtc, red,
+                                                      green, blue, size);
+               else
+                       gamma_set = crtc_get_gamma_legacy(crtc, red,
+                                                         green, blue, size);
 
                DBG(("%s: CRTC:%d, pipe=%d: gamma set?=%d\n",
                     __FUNCTION__, __sna_crtc_id(sna_crtc), 
__sna_crtc_pipe(sna_crtc),
@@ -7311,19 +7478,21 @@ static void crtc_init_gamma(xf86CrtcPtr crtc)
                if (!gamma_set) {
                        int i;
 
-                       for (i = 0; i < 256; i++) {
-                               gamma[i] = i << 8;
-                               gamma[256 + i] = i << 8;
-                               gamma[2*256 + i] = i << 8;
+                       for (i = 0; i < size; i++) {
+                               uint16_t val = i * 0xffff / (size - 1);
+
+                               red[i] = val;
+                               green[i] = val;
+                               blue[i] = val;
                        }
                }
 
-               if (gamma != crtc->gamma_red) {
+               if (red != crtc->gamma_red) {
                        free(crtc->gamma_red);
-                       crtc->gamma_red = gamma;
-                       crtc->gamma_green = gamma + 256;
-                       crtc->gamma_blue = gamma + 2*256;
-                       crtc->gamma_size = 256;
+                       crtc->gamma_red = red;
+                       crtc->gamma_green = green;
+                       crtc->gamma_blue = blue;
+                       crtc->gamma_size = size;
                }
        }
 }
-- 
2.21.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to