From: Harry Wentland <harry.wentl...@amd.com>

We add two 3x4 matrices into the VKMS color pipeline. The reason
we're adding matrices is so that we can test that application
of a matrix and its inverse yields an output equal to the input
image.

One complication with the matrix implementation has to do with
the fact that the matrix entries are in signed-magnitude fixed
point, whereas the drm_fixed.h implementation uses 2s-complement.
The latter one is the one that we want for easy addition and
subtraction, so we convert all entries to 2s-complement.

Reviewed-by: Louis Chauvet <louis.chau...@bootlin.com>
Signed-off-by: Alex Hung <alex.h...@amd.com>
Signed-off-by: Harry Wentland <harry.wentl...@amd.com>
Reviewed-by: Daniel Stone <dani...@collabora.com>
---
v11:
 - Fix comments to "2nd op 3x4 matrix" (NĂ­colas Prado)

v9:
 - Update function names by _plane_ (Chaitanya Kumar Borah)

v8:
 - Replace DRM_ERROR with drm_err (Louis Chauvet)

v7:
 - Fix checkpatch warnings
  - Change kzalloc(sizeof(struct drm_colorop) ...) to kzalloc(sizeof(*ops[i]) 
...)
  - Change i-1to i - 1
  - Add a new line at EOF

v6:
 - pre-compute colors (Louis Chauvet)
 - round matrix output (Louis Chauvet)

 drivers/gpu/drm/vkms/vkms_colorop.c  | 36 ++++++++++++++++++++++++++--
 drivers/gpu/drm/vkms/vkms_composer.c | 33 +++++++++++++++++++++++++
 2 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c 
b/drivers/gpu/drm/vkms/vkms_colorop.c
index f955ffb0ac84..3be9b204a9bf 100644
--- a/drivers/gpu/drm/vkms/vkms_colorop.c
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -12,7 +12,7 @@ static const u64 supported_tfs =
        BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
        BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
 
-#define MAX_COLOR_PIPELINE_OPS 2
+#define MAX_COLOR_PIPELINE_OPS 4
 
 static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct 
drm_prop_enum_list *list)
 {
@@ -40,7 +40,39 @@ static int vkms_initialize_color_pipeline(struct drm_plane 
*plane, struct drm_pr
 
        i++;
 
-       /* 2nd op: 1d curve */
+       /* 2nd op: 3x4 matrix */
+       ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
+       if (!ops[i]) {
+               drm_err(dev, "KMS: Failed to allocate colorop\n");
+               ret = -ENOMEM;
+               goto cleanup;
+       }
+
+       ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane);
+       if (ret)
+               goto cleanup;
+
+       drm_colorop_set_next_property(ops[i - 1], ops[i]);
+
+       i++;
+
+       /* 3rd op: 3x4 matrix */
+       ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
+       if (!ops[i]) {
+               drm_err(dev, "KMS: Failed to allocate colorop\n");
+               ret = -ENOMEM;
+               goto cleanup;
+       }
+
+       ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane);
+       if (ret)
+               goto cleanup;
+
+       drm_colorop_set_next_property(ops[i - 1], ops[i]);
+
+       i++;
+
+       /* 4th op: 1d curve */
        ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
        if (!ops[i]) {
                drm_err(dev, "KMS: Failed to allocate colorop\n");
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index 6630dccd68a4..96cdbf08e70d 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -128,6 +128,35 @@ static void apply_lut(const struct vkms_crtc_state 
*crtc_state, struct line_buff
        }
 }
 
+static void apply_3x4_matrix(struct pixel_argb_s32 *pixel, const struct 
drm_color_ctm_3x4 *matrix)
+{
+       s64 rf, gf, bf;
+       s64 r, g, b;
+
+       r = drm_int2fixp(pixel->r);
+       g = drm_int2fixp(pixel->g);
+       b = drm_int2fixp(pixel->b);
+
+       rf = drm_fixp_mul(drm_sm2fixp(matrix->matrix[0]), r) +
+            drm_fixp_mul(drm_sm2fixp(matrix->matrix[1]), g) +
+            drm_fixp_mul(drm_sm2fixp(matrix->matrix[2]), b) +
+            drm_sm2fixp(matrix->matrix[3]);
+
+       gf = drm_fixp_mul(drm_sm2fixp(matrix->matrix[4]), r) +
+            drm_fixp_mul(drm_sm2fixp(matrix->matrix[5]), g) +
+            drm_fixp_mul(drm_sm2fixp(matrix->matrix[6]), b) +
+            drm_sm2fixp(matrix->matrix[7]);
+
+       bf = drm_fixp_mul(drm_sm2fixp(matrix->matrix[8]), r) +
+            drm_fixp_mul(drm_sm2fixp(matrix->matrix[9]), g) +
+            drm_fixp_mul(drm_sm2fixp(matrix->matrix[10]), b) +
+            drm_sm2fixp(matrix->matrix[11]);
+
+       pixel->r = drm_fixp2int_round(rf);
+       pixel->g = drm_fixp2int_round(gf);
+       pixel->b = drm_fixp2int_round(bf);
+}
+
 static void apply_colorop(struct pixel_argb_s32 *pixel, struct drm_colorop 
*colorop)
 {
        struct drm_colorop_state *colorop_state = colorop->state;
@@ -151,6 +180,10 @@ static void apply_colorop(struct pixel_argb_s32 *pixel, 
struct drm_colorop *colo
                                      colorop_state->curve_1d_type);
                        break;
                }
+       } else if (colorop->type == DRM_COLOROP_CTM_3X4) {
+               if (colorop_state->data)
+                       apply_3x4_matrix(pixel,
+                                        (struct drm_color_ctm_3x4 *) 
colorop_state->data->data);
        }
 }
 
-- 
2.43.0

Reply via email to