All of lore.kernel.org
 help / color / mirror / Atom feed
From: <sunpeng.li-5C7GfCeVMHo@public.gmane.org>
To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: "Leo (Sunpeng) Li" <sunpeng.li-5C7GfCeVMHo@public.gmane.org>,
	michel-otUistvHUpPR7s880joybQ@public.gmane.org,
	harry.wentland-5C7GfCeVMHo@public.gmane.org
Subject: [PATCH xf86-video-amdgpu 6/7 v2] Compose non-legacy with legacy regamma LUT
Date: Fri, 8 Jun 2018 13:21:24 -0400	[thread overview]
Message-ID: <1528478484-31177-1-git-send-email-sunpeng.li@amd.com> (raw)
In-Reply-To: <1527869017-9209-7-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>

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

Frequently, a user may have non-legacy gamma enabled for monitor
correction, while using legacy gamma for things like
redshift/nightlight.

To do so, we compose the two LUTs. Legacy gamma will be applied first,
then non-legacy. i.e. non-legacy_LUT(legacy_LUT(in_color)).

Note that the staged gamma LUT within the driver-private CRTC will
always contain the non-legacy LUT. This is to ensure that we have a
cached copy for future compositions.

v2: Don't compose LUTs if legacy gamma is disabled (which is the case
    for deep 30bpp color). The legacy LUT won't be computed here,
    causing composition to spit out something invalid.

Signed-off-by: Leo (Sunpeng) Li <sunpeng.li@amd.com>
---
 src/drmmode_display.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 186 insertions(+), 1 deletion(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 6e5ae74..77a136e 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -788,6 +788,150 @@ static Bool drmmode_crtc_cm_enabled(drmmode_crtc_private_ptr drmmode_crtc)
 }
 
 /**
+ * If legacy LUT is a, and non-legacy LUT is b, then the result of b(a(x)) is
+ * returned in out_lut. out_lut's length is expected to be the same as the
+ * non-legacy LUT b.
+ *
+ * @a_(red|green|blue): The red, green, and blue components of the legacy LUT.
+ * @b_lut: The non-legacy LUT, in DRM's color LUT format.
+ * @out_lut: The composed LUT, in DRM's color LUT format.
+ * @len_a: Length of legacy lut.
+ * @len_b: Length of non-legacy lut.
+ */
+static void drmmode_lut_compose(uint16_t *a_red,
+				uint16_t *a_green,
+				uint16_t *a_blue,
+				struct drm_color_lut *b_lut,
+				struct drm_color_lut *out_lut,
+				uint32_t len_a, uint32_t len_b)
+{
+	uint32_t i_l, i_r, i;
+	uint32_t i_amax, i_bmax;
+	uint32_t coeff_ibmax;
+	uint32_t j;
+	uint64_t a_out_ibmax;
+	int color;
+	size_t struct_size = sizeof(struct drm_color_lut);
+
+	uint32_t max_lut = (1 << 16) - 1;
+
+	i_amax = len_a - 1;
+	i_bmax = len_b - 1;
+
+	/* A linear interpolation is done on the legacy LUT before it is
+	 * composed, to bring it up-to-size with the non-legacy LUT. The
+	 * interpolation uses integers by keeping things multiplied until the
+	 * last moment.
+	 */
+	for (color = 0; color < 3; color++) {
+		uint16_t *a, *b, *out;
+
+		/* Set the initial pointers to the right color components. The
+		 * inner for-loop will then maintain the correct offset from
+		 * the initial element.
+		 */
+		if (color == 0) {
+			a = a_red;
+			b = &b_lut[0].red;
+			out = &out_lut[0].red;
+		} else if (color == 1) {
+			a = a_green;
+			b = &b_lut[0].green;
+			out = &out_lut[0].green;
+		} else {
+			a = a_blue;
+			b = &b_lut[0].blue;
+			out = &out_lut[0].blue;
+		}
+
+		for (i = 0; i < len_b; i++) {
+			/* i_l and i_r tracks the left and right elements in
+			 * a_lut, to the sample point i. Also handle last
+			 * element edge case, when i_l = i_amax.
+			 */
+			i_l = i * i_amax / i_bmax;
+			i_r = i_l + !!(i_amax - i_l);
+
+			/* coeff is intended to be in [0, 1), depending on
+			 * where sample i is between i_l and i_r. We keep it
+			 * multiplied with i_bmax throughout to maintain
+			 * precision */
+			coeff_ibmax = (i * i_amax) - (i_l * i_bmax);
+			a_out_ibmax = i_bmax * a[i_l] +
+				      coeff_ibmax * (a[i_r] - a[i_l]);
+
+			/* j = floor((a_out/max_lut)*i_bmax).
+			 * i.e. the element in LUT b that a_out maps to. We
+			 * have to divide by max_lut to normalize a_out, since
+			 * values in the LUTs are [0, 1<<16)
+			 */
+			j = a_out_ibmax / max_lut;
+			*(uint16_t*)((void*)out + (i*struct_size)) =
+				*(uint16_t*)((void*)b + (j*struct_size));
+		}
+	}
+
+	for (i = 0; i < len_b; i++)
+		out_lut[i].reserved = 0;
+}
+
+/**
+ * Resize a LUT, using linear interpolation.
+ *
+ * @in_(red|green|blue): Legacy LUT components
+ * @out_lut: The resized LUT is returned here, in DRM color LUT format.
+ * @len_in: Length of legacy LUT.
+ * @len_out: Length of out_lut, i.e. the target size.
+ */
+static void drmmode_lut_interpolate(uint16_t *in_red,
+				    uint16_t *in_green,
+				    uint16_t *in_blue,
+				    struct drm_color_lut *out_lut,
+				    uint32_t len_in, uint32_t len_out)
+{
+	uint32_t i_l, i_r, i;
+	uint32_t i_amax, i_bmax;
+	uint32_t coeff_ibmax;
+	uint64_t out_ibmax;
+	int color;
+	size_t struct_size = sizeof(struct drm_color_lut);
+
+	i_amax = len_in - 1;
+	i_bmax = len_out - 1;
+
+	/* See @drmmode_lut_compose for details */
+	for (color = 0; color < 3; color++) {
+		uint16_t *in, *out;
+
+		if (color == 0) {
+			in = in_red;
+			out = &out_lut[0].red;
+		} else if (color == 1) {
+			in = in_green;
+			out = &out_lut[0].green;
+		} else {
+			in = in_blue;
+			out = &out_lut[0].blue;
+		}
+
+		for (i = 0; i < len_out; i++) {
+			i_l = i * i_amax / i_bmax;
+			i_r = i_l + !!(i_amax - i_l);
+
+			coeff_ibmax = (i * i_amax) - (i_l * i_bmax);
+			out_ibmax = i_bmax * in[i_l] +
+				      coeff_ibmax * (in[i_r] - in[i_l]);
+
+			*(uint16_t*)((void*)out + (i*struct_size)) =
+				out_ibmax / i_bmax;
+		}
+	}
+
+	for (i = 0; i < len_out; i++)
+		out_lut[i].reserved = 0;
+}
+
+/**
  * Configure and change a color property on a CRTC, through RandR. Only the
  * specified output will be affected, even if the CRTC is attached to multiple
  * outputs. Note that changes will be non-pending: the changes won't be pushed
@@ -1000,6 +1144,7 @@ static int drmmode_crtc_push_cm_prop(xf86CrtcPtr crtc,
 {
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
+	Bool free_blob_data = FALSE;
 	uint32_t created_blob_id = 0;
 	uint32_t drm_prop_id;
 	size_t expected_bytes = 0;
@@ -1013,7 +1158,39 @@ static int drmmode_crtc_push_cm_prop(xf86CrtcPtr crtc,
 		/* 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;
+
+		/* Legacy gamma LUT is disabled on deep 30bpp color. In which
+		 * case, directly use non-legacy LUT.
+		 */
+		if (crtc->funcs->gamma_set == NULL) {
+			blob_data = drmmode_crtc->gamma_lut;
+			goto do_push;
+		}
+
+		blob_data = malloc(expected_bytes);
+		if (!blob_data)
+			return BadAlloc;
+
+		free_blob_data = TRUE;
+		/*
+		 * Compose legacy and non-legacy LUT if non-legacy was set.
+		 * Otherwise, interpolate legacy LUT to non-legacy size.
+		 */
+		if (drmmode_crtc->gamma_lut) {
+			drmmode_lut_compose(crtc->gamma_red,
+					    crtc->gamma_green,
+					    crtc->gamma_blue,
+					    drmmode_crtc->gamma_lut,
+					    blob_data, crtc->gamma_size,
+					    drmmode_crtc->gamma_lut_size);
+		} else {
+			drmmode_lut_interpolate(crtc->gamma_red,
+						crtc->gamma_green,
+						crtc->gamma_blue,
+						blob_data,
+						crtc->gamma_size,
+						drmmode_crtc->gamma_lut_size);
+		}
 	} else if (cm_prop_index == CM_DEGAMMA_LUT) {
 		expected_bytes = sizeof(struct drm_color_lut) *
 					drmmode_crtc->degamma_lut_size;
@@ -1024,6 +1201,7 @@ static int drmmode_crtc_push_cm_prop(xf86CrtcPtr crtc,
 	} else
 		return BadName;
 
+do_push:
 	if (blob_data) {
 		ret = drmModeCreatePropertyBlob(pAMDGPUEnt->fd,
 						blob_data, expected_bytes,
@@ -1032,6 +1210,8 @@ static int drmmode_crtc_push_cm_prop(xf86CrtcPtr crtc,
 			xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
 				   "Creating DRM blob failed with errno %d\n",
 				   ret);
+			if (free_blob_data)
+				free(blob_data);
 			return BadRequest;
 		}
 	}
@@ -1053,9 +1233,14 @@ static int drmmode_crtc_push_cm_prop(xf86CrtcPtr crtc,
 		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
 			   "Setting DRM property blob failed with errno %d\n",
 			   ret);
+		if (free_blob_data)
+			free(blob_data);
 		return BadRequest;
 	}
 
+	if (free_blob_data)
+		free(blob_data);
+
 	return Success;
 }
 
-- 
2.7.4

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

  parent reply	other threads:[~2018-06-08 17:21 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-01 16:03 [PATCH xf86-video-amdgpu 0/7] Enabling Color Management - Round 3 sunpeng.li-5C7GfCeVMHo
     [not found] ` <1527869017-9209-1-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2018-06-01 16:03   ` [PATCH xf86-video-amdgpu 1/7] Cache color property IDs during pre-init sunpeng.li-5C7GfCeVMHo
     [not found]     ` <1527869017-9209-2-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2018-06-15 21:02       ` [PATCH xf86-video-amdgpu v2 1/7] Cache color property IDs and LUT sizes " sunpeng.li-5C7GfCeVMHo
2018-06-01 16:03   ` [PATCH xf86-video-amdgpu 2/7] Initialize color properties on CRTC during CRTC init sunpeng.li-5C7GfCeVMHo
     [not found]     ` <1527869017-9209-3-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2018-06-14 16:58       ` Michel Dänzer
2018-06-15 21:04       ` [PATCH xf86-video-amdgpu v2 " sunpeng.li-5C7GfCeVMHo
2018-06-01 16:03   ` [PATCH xf86-video-amdgpu 3/7] Configure color properties when creating output resources sunpeng.li-5C7GfCeVMHo
     [not found]     ` <1527869017-9209-4-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2018-06-14 16:58       ` Michel Dänzer
2018-06-15 21:04       ` [PATCH xf86-video-amdgpu v2 " sunpeng.li-5C7GfCeVMHo
2018-06-01 16:03   ` [PATCH xf86-video-amdgpu 4/7] Update color properties on output_get_property sunpeng.li-5C7GfCeVMHo
     [not found]     ` <1527869017-9209-5-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2018-06-15 21:05       ` [PATCH xf86-video-amdgpu v2 " sunpeng.li-5C7GfCeVMHo
2018-06-01 16:03   ` [PATCH xf86-video-amdgpu 5/7] Enable setting of color properties via RandR sunpeng.li-5C7GfCeVMHo
     [not found]     ` <1527869017-9209-6-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2018-06-15 21:05       ` [PATCH xf86-video-amdgpu v2 " sunpeng.li-5C7GfCeVMHo
2018-06-01 16:03   ` [PATCH xf86-video-amdgpu 6/7] Compose non-legacy with legacy regamma LUT sunpeng.li-5C7GfCeVMHo
     [not found]     ` <1527869017-9209-7-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2018-06-08 17:21       ` sunpeng.li-5C7GfCeVMHo [this message]
     [not found]         ` <1528478484-31177-1-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2018-06-15 21:12           ` [PATCH xf86-video-amdgpu v3 " sunpeng.li-5C7GfCeVMHo
2018-06-01 16:03   ` [PATCH xf86-video-amdgpu 7/7] Also compose LUT when setting legacy gamma sunpeng.li-5C7GfCeVMHo
     [not found]     ` <1527869017-9209-8-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2018-06-15 21:05       ` [PATCH xf86-video-amdgpu v2 " sunpeng.li-5C7GfCeVMHo
2018-06-06 16:01   ` [PATCH xf86-video-amdgpu 0/7] Enabling Color Management - Round 3 Michel Dänzer
     [not found]     ` <e0a71df1-265b-cb62-1c1f-567b26808b71-otUistvHUpPR7s880joybQ@public.gmane.org>
2018-06-06 17:03       ` Michel Dänzer
     [not found]         ` <e47b6ff4-9696-bf20-d299-687b96ab0437-otUistvHUpPR7s880joybQ@public.gmane.org>
2018-06-06 17:22           ` Leo Li
2018-06-07  7:36           ` Michel Dänzer
2018-06-07 22:21           ` Leo Li
     [not found]             ` <9392443d-13d4-c1c2-c07b-67a2b6c72556-5C7GfCeVMHo@public.gmane.org>
2018-06-08 14:33               ` Michel Dänzer
     [not found]                 ` <8807a407-352d-3caa-108a-95aadcd6b414-otUistvHUpPR7s880joybQ@public.gmane.org>
2018-06-08 14:37                   ` Michel Dänzer
2018-06-07  7:22       ` Mike Lothian
     [not found]         ` <CAHbf0-GW9MDmTBDepJjG-WXdqNPhsHWwQMvHo1Sma+JCDy-1dQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2018-06-07  7:31           ` Michel Dänzer
     [not found]             ` <64b1e3fc-d267-b1fc-032a-86aebfe2ff1d-otUistvHUpPR7s880joybQ@public.gmane.org>
2018-06-07 13:26               ` Mike Lothian
     [not found]                 ` <CAHbf0-E=KyYDVj-L5fknEPGL6kUeP--bDOuPXUz5oMjciABXYw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2018-06-07 13:55                   ` Michel Dänzer
2018-06-14 16:57   ` Michel Dänzer
     [not found]     ` <afdb23a3-8722-7928-a612-291b42e7f260-otUistvHUpPR7s880joybQ@public.gmane.org>
2018-06-14 19:49       ` Leo Li
     [not found]         ` <a5a043dd-cd40-33bc-1e1d-e3f8980cb69d-5C7GfCeVMHo@public.gmane.org>
2018-06-15  6:57           ` Michel Dänzer
     [not found]             ` <b64b3eea-5780-ef62-2b59-b2e4733ead16-otUistvHUpPR7s880joybQ@public.gmane.org>
2018-06-22 13:41               ` Leo Li
     [not found]                 ` <09c87c7a-76ed-062e-d911-5b188e3ed5cb-5C7GfCeVMHo@public.gmane.org>
2018-06-22 13:49                   ` Michel Dänzer
2018-06-26 15:46                   ` Michel Dänzer
     [not found]                     ` <d977b737-6d9d-de47-6a37-763af76efa54-otUistvHUpPR7s880joybQ@public.gmane.org>
2018-06-26 18:16                       ` Harry Wentland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1528478484-31177-1-git-send-email-sunpeng.li@amd.com \
    --to=sunpeng.li-5c7gfcevmho@public.gmane.org \
    --cc=amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    --cc=harry.wentland-5C7GfCeVMHo@public.gmane.org \
    --cc=michel-otUistvHUpPR7s880joybQ@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.