AMD-GFX Archive on 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] Compose non-legacy with legacy regamma LUT
Date: Fri, 1 Jun 2018 12:03:36 -0400	[thread overview]
Message-ID: <1527869017-9209-7-git-send-email-sunpeng.li@amd.com> (raw)
In-Reply-To: <1527869017-9209-1-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.

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

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 6e5ae74..b4e1d57 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,30 @@ 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;
+
+		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;
@@ -1032,6 +1200,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 +1223,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-01 16:03 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   ` sunpeng.li-5C7GfCeVMHo [this message]
     [not found]     ` <1527869017-9209-7-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2018-06-08 17:21       ` [PATCH xf86-video-amdgpu 6/7 v2] Compose non-legacy with legacy regamma LUT sunpeng.li-5C7GfCeVMHo
     [not found]         ` <1528478484-31177-1-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2018-06-15 21:12           ` [PATCH xf86-video-amdgpu v3 6/7] " 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=1527869017-9209-7-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox