diff mbox series

[RFC,10/10] drm/vkms: Add enumerated 1D curve colorop

Message ID 20230908150235.75918-11-harry.wentland@amd.com (mailing list archive)
State New, archived
Headers show
Series Color Pipeline API w/ VKMS | expand

Commit Message

Harry Wentland Sept. 8, 2023, 3:02 p.m. UTC
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Pekka Paalanen <pekka.paalanen@collabora.com>
Cc: Simon Ser <contact@emersion.fr>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: Melissa Wen <mwen@igalia.com>
Cc: Jonas Ådahl <jadahl@redhat.com>
Cc: Sebastian Wick <sebastian.wick@redhat.com>
Cc: Shashank Sharma <shashank.sharma@amd.com>
Cc: Alexander Goins <agoins@nvidia.com>
Cc: Joshua Ashton <joshua@froggi.es>
Cc: Michel Dänzer <mdaenzer@redhat.com>
Cc: Aleix Pol <aleixpol@kde.org>
Cc: Xaver Hugl <xaver.hugl@gmail.com>
Cc: Victoria Brekenfeld <victoria@system76.com>
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: Uma Shankar <uma.shankar@intel.com>
Cc: Naseer Ahmed <quic_naseer@quicinc.com>
Cc: Christopher Braga <quic_cbraga@quicinc.com>
---
 drivers/gpu/drm/vkms/Makefile        |   3 +-
 drivers/gpu/drm/vkms/vkms_colorop.c  | 108 +++++++++
 drivers/gpu/drm/vkms/vkms_composer.c | 316 +++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_drv.h      |   4 +
 drivers/gpu/drm/vkms/vkms_plane.c    |   2 +
 5 files changed, 432 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/vkms/vkms_colorop.c

Comments

Melissa Wen Oct. 10, 2023, 4:27 p.m. UTC | #1
On 09/08, Harry Wentland wrote:
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> Cc: Pekka Paalanen <pekka.paalanen@collabora.com>
> Cc: Simon Ser <contact@emersion.fr>
> Cc: Harry Wentland <harry.wentland@amd.com>
> Cc: Melissa Wen <mwen@igalia.com>
> Cc: Jonas Ådahl <jadahl@redhat.com>
> Cc: Sebastian Wick <sebastian.wick@redhat.com>
> Cc: Shashank Sharma <shashank.sharma@amd.com>
> Cc: Alexander Goins <agoins@nvidia.com>
> Cc: Joshua Ashton <joshua@froggi.es>
> Cc: Michel Dänzer <mdaenzer@redhat.com>
> Cc: Aleix Pol <aleixpol@kde.org>
> Cc: Xaver Hugl <xaver.hugl@gmail.com>
> Cc: Victoria Brekenfeld <victoria@system76.com>
> Cc: Daniel Vetter <daniel@ffwll.ch>
> Cc: Uma Shankar <uma.shankar@intel.com>
> Cc: Naseer Ahmed <quic_naseer@quicinc.com>
> Cc: Christopher Braga <quic_cbraga@quicinc.com>
> ---
>  drivers/gpu/drm/vkms/Makefile        |   3 +-
>  drivers/gpu/drm/vkms/vkms_colorop.c  | 108 +++++++++
>  drivers/gpu/drm/vkms/vkms_composer.c | 316 +++++++++++++++++++++++++++
>  drivers/gpu/drm/vkms/vkms_drv.h      |   4 +
>  drivers/gpu/drm/vkms/vkms_plane.c    |   2 +
>  5 files changed, 432 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/vkms/vkms_colorop.c
> 
> diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
> index 1b28a6a32948..bcf508873622 100644
> --- a/drivers/gpu/drm/vkms/Makefile
> +++ b/drivers/gpu/drm/vkms/Makefile
> @@ -6,6 +6,7 @@ vkms-y := \
>  	vkms_formats.o \
>  	vkms_crtc.o \
>  	vkms_composer.o \
> -	vkms_writeback.o
> +	vkms_writeback.o \
> +	vkms_colorop.o
>  
>  obj-$(CONFIG_DRM_VKMS) += vkms.o
> diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
> new file mode 100644
> index 000000000000..b3da0705bca7
> --- /dev/null
> +++ b/drivers/gpu/drm/vkms/vkms_colorop.c
> @@ -0,0 +1,108 @@
> +/*
> + * Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + * Authors: AMD
> + *
> + */
> +
> +#include <linux/slab.h>
> +#include <drm/drm_colorop.h>
> +#include <drm/drm_print.h>
> +#include <drm/drm_property.h>
> +#include <drm/drm_plane.h>
> +
> +#define MAX_COLOR_PIPELINES 5
> +
> +const int vkms_initialize_tf_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
> +{
> +
> +	struct drm_colorop *op, *prev_op;
> +	struct drm_device *dev = plane->dev;
> +	int ret;
> +
> +	/* 1st op: 1d curve */
> +	op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
> +	if (!op) {
> +		DRM_ERROR("KMS: Failed to allocate colorop\n");
> +		return -ENOMEM;
> +	}
> +
> +	ret = drm_colorop_init(dev, op, plane, DRM_COLOROP_1D_CURVE);
> +	if (ret)
> +		return ret;
> +
> +	list->type = op->base.id;
> +	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", op->base.id);
> +
> +	prev_op = op;
> +
> +	/* 2nd op: 1d curve */
> +	op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
> +	if (!op) {
> +		DRM_ERROR("KMS: Failed to allocate colorop\n");
> +		return -ENOMEM;
> +	}
> +
> +	ret = drm_colorop_init(dev, op, plane, DRM_COLOROP_1D_CURVE);
> +	if (ret)
> +		return ret;
> +
> +	drm_colorop_set_next_property(prev_op, op);
> +
> +	return 0;
> +}
> +
> +int vkms_initialize_colorops(struct drm_plane *plane)
> +{
> +	struct drm_device *dev = plane->dev;
> +	struct drm_property *prop;
> +	struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
> +	int len = 0;
> +	int ret;
> +
> +	/* Add "Bypass" (i.e. NULL) pipeline */
> +	pipelines[len].type = 0;
> +	pipelines[len].name = "Bypass";
> +	len++;
> +
> +	/* Add pipeline consisting of transfer functions */
> +	ret = vkms_initialize_tf_pipeline(plane, &(pipelines[len]));
> +	if (ret)
> +		return ret;
> +	len++;
> +
> +	/* Create COLOR_PIPELINE property and attach */
> +	prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC,
> +					"COLOR_PIPELINE",
> +					pipelines, len);
> +	if (!prop)
> +		return -ENOMEM;
> +
> +	plane->color_pipeline_property = prop;
> +
> +	drm_object_attach_property(&plane->base, prop, 0);
> +
> +	/* TODO do we even need this? */
> +	if (plane->state)
> +		plane->state->color_pipeline = NULL;
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
> index f6c311e8a87c..92ab9c62a554 100644
> --- a/drivers/gpu/drm/vkms/vkms_composer.c
> +++ b/drivers/gpu/drm/vkms/vkms_composer.c
> @@ -12,6 +12,284 @@
>  
>  #include "vkms_drv.h"
>  
> +#define LUT_SIZE 256
> +
> +struct drm_color_lut srgb_array[LUT_SIZE] = {
> +	{ 0x13, 0x13, 0x13, 0 },
> +	{ 0x27, 0x27, 0x27, 0 },
> +	{ 0x3b, 0x3b, 0x3b, 0 },
> +	{ 0x4f, 0x4f, 0x4f, 0 },
> +	{ 0x63, 0x63, 0x63, 0 },
> +	{ 0x76, 0x76, 0x76, 0 },
> +	{ 0x8a, 0x8a, 0x8a, 0 },
> +	{ 0x9e, 0x9e, 0x9e, 0 },
> +	{ 0xb2, 0xb2, 0xb2, 0 },
> +	{ 0xc6, 0xc6, 0xc6, 0 },
> +	{ 0xda, 0xda, 0xda, 0 },
> +	{ 0xef, 0xef, 0xef, 0 },
> +	{ 0x106, 0x106, 0x106, 0 },
> +	{ 0x11e, 0x11e, 0x11e, 0 },
> +	{ 0x137, 0x137, 0x137, 0 },
> +	{ 0x151, 0x151, 0x151, 0 },
> +	{ 0x16d, 0x16d, 0x16d, 0 },
> +	{ 0x18a, 0x18a, 0x18a, 0 },
> +	{ 0x1a8, 0x1a8, 0x1a8, 0 },
> +	{ 0x1c7, 0x1c7, 0x1c7, 0 },
> +	{ 0x1e8, 0x1e8, 0x1e8, 0 },
> +	{ 0x20a, 0x20a, 0x20a, 0 },
> +	{ 0x22e, 0x22e, 0x22e, 0 },
> +	{ 0x253, 0x253, 0x253, 0 },
> +	{ 0x279, 0x279, 0x279, 0 },
> +	{ 0x2a0, 0x2a0, 0x2a0, 0 },
> +	{ 0x2c9, 0x2c9, 0x2c9, 0 },
> +	{ 0x2f4, 0x2f4, 0x2f4, 0 },
> +	{ 0x320, 0x320, 0x320, 0 },
> +	{ 0x34d, 0x34d, 0x34d, 0 },
> +	{ 0x37c, 0x37c, 0x37c, 0 },
> +	{ 0x3ac, 0x3ac, 0x3ac, 0 },
> +	{ 0x3de, 0x3de, 0x3de, 0 },
> +	{ 0x411, 0x411, 0x411, 0 },
> +	{ 0x446, 0x446, 0x446, 0 },
> +	{ 0x47c, 0x47c, 0x47c, 0 },
> +	{ 0x4b4, 0x4b4, 0x4b4, 0 },
> +	{ 0x4ed, 0x4ed, 0x4ed, 0 },
> +	{ 0x528, 0x528, 0x528, 0 },
> +	{ 0x564, 0x564, 0x564, 0 },
> +	{ 0x5a3, 0x5a3, 0x5a3, 0 },
> +	{ 0x5e2, 0x5e2, 0x5e2, 0 },
> +	{ 0x624, 0x624, 0x624, 0 },
> +	{ 0x666, 0x666, 0x666, 0 },
> +	{ 0x6ab, 0x6ab, 0x6ab, 0 },
> +	{ 0x6f1, 0x6f1, 0x6f1, 0 },
> +	{ 0x739, 0x739, 0x739, 0 },
> +	{ 0x782, 0x782, 0x782, 0 },
> +	{ 0x7ce, 0x7ce, 0x7ce, 0 },
> +	{ 0x81b, 0x81b, 0x81b, 0 },
> +	{ 0x869, 0x869, 0x869, 0 },
> +	{ 0x8b9, 0x8b9, 0x8b9, 0 },
> +	{ 0x90b, 0x90b, 0x90b, 0 },
> +	{ 0x95f, 0x95f, 0x95f, 0 },
> +	{ 0x9b5, 0x9b5, 0x9b5, 0 },
> +	{ 0xa0c, 0xa0c, 0xa0c, 0 },
> +	{ 0xa65, 0xa65, 0xa65, 0 },
> +	{ 0xabf, 0xabf, 0xabf, 0 },
> +	{ 0xb1c, 0xb1c, 0xb1c, 0 },
> +	{ 0xb7a, 0xb7a, 0xb7a, 0 },
> +	{ 0xbda, 0xbda, 0xbda, 0 },
> +	{ 0xc3c, 0xc3c, 0xc3c, 0 },
> +	{ 0xca0, 0xca0, 0xca0, 0 },
> +	{ 0xd06, 0xd06, 0xd06, 0 },
> +	{ 0xd6d, 0xd6d, 0xd6d, 0 },
> +	{ 0xdd6, 0xdd6, 0xdd6, 0 },
> +	{ 0xe41, 0xe41, 0xe41, 0 },
> +	{ 0xeae, 0xeae, 0xeae, 0 },
> +	{ 0xf1d, 0xf1d, 0xf1d, 0 },
> +	{ 0xf8e, 0xf8e, 0xf8e, 0 },
> +	{ 0x1001, 0x1001, 0x1001, 0 },
> +	{ 0x1075, 0x1075, 0x1075, 0 },
> +	{ 0x10ec, 0x10ec, 0x10ec, 0 },
> +	{ 0x1164, 0x1164, 0x1164, 0 },
> +	{ 0x11de, 0x11de, 0x11de, 0 },
> +	{ 0x125a, 0x125a, 0x125a, 0 },
> +	{ 0x12d9, 0x12d9, 0x12d9, 0 },
> +	{ 0x1359, 0x1359, 0x1359, 0 },
> +	{ 0x13db, 0x13db, 0x13db, 0 },
> +	{ 0x145f, 0x145f, 0x145f, 0 },
> +	{ 0x14e5, 0x14e5, 0x14e5, 0 },
> +	{ 0x156d, 0x156d, 0x156d, 0 },
> +	{ 0x15f7, 0x15f7, 0x15f7, 0 },
> +	{ 0x1683, 0x1683, 0x1683, 0 },
> +	{ 0x1711, 0x1711, 0x1711, 0 },
> +	{ 0x17a1, 0x17a1, 0x17a1, 0 },
> +	{ 0x1833, 0x1833, 0x1833, 0 },
> +	{ 0x18c7, 0x18c7, 0x18c7, 0 },
> +	{ 0x195d, 0x195d, 0x195d, 0 },
> +	{ 0x19f6, 0x19f6, 0x19f6, 0 },
> +	{ 0x1a90, 0x1a90, 0x1a90, 0 },
> +	{ 0x1b2c, 0x1b2c, 0x1b2c, 0 },
> +	{ 0x1bcb, 0x1bcb, 0x1bcb, 0 },
> +	{ 0x1c6b, 0x1c6b, 0x1c6b, 0 },
> +	{ 0x1d0e, 0x1d0e, 0x1d0e, 0 },
> +	{ 0x1db3, 0x1db3, 0x1db3, 0 },
> +	{ 0x1e59, 0x1e59, 0x1e59, 0 },
> +	{ 0x1f02, 0x1f02, 0x1f02, 0 },
> +	{ 0x1fad, 0x1fad, 0x1fad, 0 },
> +	{ 0x205b, 0x205b, 0x205b, 0 },
> +	{ 0x210a, 0x210a, 0x210a, 0 },
> +	{ 0x21bb, 0x21bb, 0x21bb, 0 },
> +	{ 0x226f, 0x226f, 0x226f, 0 },
> +	{ 0x2325, 0x2325, 0x2325, 0 },
> +	{ 0x23dd, 0x23dd, 0x23dd, 0 },
> +	{ 0x2497, 0x2497, 0x2497, 0 },
> +	{ 0x2553, 0x2553, 0x2553, 0 },
> +	{ 0x2612, 0x2612, 0x2612, 0 },
> +	{ 0x26d2, 0x26d2, 0x26d2, 0 },
> +	{ 0x2795, 0x2795, 0x2795, 0 },
> +	{ 0x285a, 0x285a, 0x285a, 0 },
> +	{ 0x2922, 0x2922, 0x2922, 0 },
> +	{ 0x29eb, 0x29eb, 0x29eb, 0 },
> +	{ 0x2ab7, 0x2ab7, 0x2ab7, 0 },
> +	{ 0x2b85, 0x2b85, 0x2b85, 0 },
> +	{ 0x2c56, 0x2c56, 0x2c56, 0 },
> +	{ 0x2d28, 0x2d28, 0x2d28, 0 },
> +	{ 0x2dfd, 0x2dfd, 0x2dfd, 0 },
> +	{ 0x2ed4, 0x2ed4, 0x2ed4, 0 },
> +	{ 0x2fad, 0x2fad, 0x2fad, 0 },
> +	{ 0x3089, 0x3089, 0x3089, 0 },
> +	{ 0x3167, 0x3167, 0x3167, 0 },
> +	{ 0x3247, 0x3247, 0x3247, 0 },
> +	{ 0x332a, 0x332a, 0x332a, 0 },
> +	{ 0x340e, 0x340e, 0x340e, 0 },
> +	{ 0x34f5, 0x34f5, 0x34f5, 0 },
> +	{ 0x35df, 0x35df, 0x35df, 0 },
> +	{ 0x36cb, 0x36cb, 0x36cb, 0 },
> +	{ 0x37b9, 0x37b9, 0x37b9, 0 },
> +	{ 0x38a9, 0x38a9, 0x38a9, 0 },
> +	{ 0x399c, 0x399c, 0x399c, 0 },
> +	{ 0x3a91, 0x3a91, 0x3a91, 0 },
> +	{ 0x3b89, 0x3b89, 0x3b89, 0 },
> +	{ 0x3c83, 0x3c83, 0x3c83, 0 },
> +	{ 0x3d7f, 0x3d7f, 0x3d7f, 0 },
> +	{ 0x3e7e, 0x3e7e, 0x3e7e, 0 },
> +	{ 0x3f7f, 0x3f7f, 0x3f7f, 0 },
> +	{ 0x4082, 0x4082, 0x4082, 0 },
> +	{ 0x4188, 0x4188, 0x4188, 0 },
> +	{ 0x4290, 0x4290, 0x4290, 0 },
> +	{ 0x439b, 0x439b, 0x439b, 0 },
> +	{ 0x44a8, 0x44a8, 0x44a8, 0 },
> +	{ 0x45b7, 0x45b7, 0x45b7, 0 },
> +	{ 0x46c9, 0x46c9, 0x46c9, 0 },
> +	{ 0x47dd, 0x47dd, 0x47dd, 0 },
> +	{ 0x48f4, 0x48f4, 0x48f4, 0 },
> +	{ 0x4a0d, 0x4a0d, 0x4a0d, 0 },
> +	{ 0x4b29, 0x4b29, 0x4b29, 0 },
> +	{ 0x4c47, 0x4c47, 0x4c47, 0 },
> +	{ 0x4d68, 0x4d68, 0x4d68, 0 },
> +	{ 0x4e8b, 0x4e8b, 0x4e8b, 0 },
> +	{ 0x4fb1, 0x4fb1, 0x4fb1, 0 },
> +	{ 0x50d9, 0x50d9, 0x50d9, 0 },
> +	{ 0x5203, 0x5203, 0x5203, 0 },
> +	{ 0x5330, 0x5330, 0x5330, 0 },
> +	{ 0x5460, 0x5460, 0x5460, 0 },
> +	{ 0x5592, 0x5592, 0x5592, 0 },
> +	{ 0x56c6, 0x56c6, 0x56c6, 0 },
> +	{ 0x57fd, 0x57fd, 0x57fd, 0 },
> +	{ 0x5937, 0x5937, 0x5937, 0 },
> +	{ 0x5a73, 0x5a73, 0x5a73, 0 },
> +	{ 0x5bb2, 0x5bb2, 0x5bb2, 0 },
> +	{ 0x5cf3, 0x5cf3, 0x5cf3, 0 },
> +	{ 0x5e37, 0x5e37, 0x5e37, 0 },
> +	{ 0x5f7d, 0x5f7d, 0x5f7d, 0 },
> +	{ 0x60c6, 0x60c6, 0x60c6, 0 },
> +	{ 0x6212, 0x6212, 0x6212, 0 },
> +	{ 0x6360, 0x6360, 0x6360, 0 },
> +	{ 0x64b0, 0x64b0, 0x64b0, 0 },
> +	{ 0x6604, 0x6604, 0x6604, 0 },
> +	{ 0x6759, 0x6759, 0x6759, 0 },
> +	{ 0x68b2, 0x68b2, 0x68b2, 0 },
> +	{ 0x6a0d, 0x6a0d, 0x6a0d, 0 },
> +	{ 0x6b6a, 0x6b6a, 0x6b6a, 0 },
> +	{ 0x6ccb, 0x6ccb, 0x6ccb, 0 },
> +	{ 0x6e2d, 0x6e2d, 0x6e2d, 0 },
> +	{ 0x6f93, 0x6f93, 0x6f93, 0 },
> +	{ 0x70fb, 0x70fb, 0x70fb, 0 },
> +	{ 0x7266, 0x7266, 0x7266, 0 },
> +	{ 0x73d3, 0x73d3, 0x73d3, 0 },
> +	{ 0x7543, 0x7543, 0x7543, 0 },
> +	{ 0x76b6, 0x76b6, 0x76b6, 0 },
> +	{ 0x782b, 0x782b, 0x782b, 0 },
> +	{ 0x79a3, 0x79a3, 0x79a3, 0 },
> +	{ 0x7b1d, 0x7b1d, 0x7b1d, 0 },
> +	{ 0x7c9b, 0x7c9b, 0x7c9b, 0 },
> +	{ 0x7e1b, 0x7e1b, 0x7e1b, 0 },
> +	{ 0x7f9d, 0x7f9d, 0x7f9d, 0 },
> +	{ 0x8123, 0x8123, 0x8123, 0 },
> +	{ 0x82ab, 0x82ab, 0x82ab, 0 },
> +	{ 0x8436, 0x8436, 0x8436, 0 },
> +	{ 0x85c3, 0x85c3, 0x85c3, 0 },
> +	{ 0x8753, 0x8753, 0x8753, 0 },
> +	{ 0x88e6, 0x88e6, 0x88e6, 0 },
> +	{ 0x8a7c, 0x8a7c, 0x8a7c, 0 },
> +	{ 0x8c14, 0x8c14, 0x8c14, 0 },
> +	{ 0x8daf, 0x8daf, 0x8daf, 0 },
> +	{ 0x8f4d, 0x8f4d, 0x8f4d, 0 },
> +	{ 0x90ed, 0x90ed, 0x90ed, 0 },
> +	{ 0x9290, 0x9290, 0x9290, 0 },
> +	{ 0x9436, 0x9436, 0x9436, 0 },
> +	{ 0x95df, 0x95df, 0x95df, 0 },
> +	{ 0x978b, 0x978b, 0x978b, 0 },
> +	{ 0x9939, 0x9939, 0x9939, 0 },
> +	{ 0x9aea, 0x9aea, 0x9aea, 0 },
> +	{ 0x9c9e, 0x9c9e, 0x9c9e, 0 },
> +	{ 0x9e55, 0x9e55, 0x9e55, 0 },
> +	{ 0xa00e, 0xa00e, 0xa00e, 0 },
> +	{ 0xa1ca, 0xa1ca, 0xa1ca, 0 },
> +	{ 0xa389, 0xa389, 0xa389, 0 },
> +	{ 0xa54b, 0xa54b, 0xa54b, 0 },
> +	{ 0xa710, 0xa710, 0xa710, 0 },
> +	{ 0xa8d7, 0xa8d7, 0xa8d7, 0 },
> +	{ 0xaaa1, 0xaaa1, 0xaaa1, 0 },
> +	{ 0xac6e, 0xac6e, 0xac6e, 0 },
> +	{ 0xae3e, 0xae3e, 0xae3e, 0 },
> +	{ 0xb011, 0xb011, 0xb011, 0 },
> +	{ 0xb1e7, 0xb1e7, 0xb1e7, 0 },
> +	{ 0xb3bf, 0xb3bf, 0xb3bf, 0 },
> +	{ 0xb59a, 0xb59a, 0xb59a, 0 },
> +	{ 0xb778, 0xb778, 0xb778, 0 },
> +	{ 0xb959, 0xb959, 0xb959, 0 },
> +	{ 0xbb3d, 0xbb3d, 0xbb3d, 0 },
> +	{ 0xbd24, 0xbd24, 0xbd24, 0 },
> +	{ 0xbf0d, 0xbf0d, 0xbf0d, 0 },
> +	{ 0xc0fa, 0xc0fa, 0xc0fa, 0 },
> +	{ 0xc2e9, 0xc2e9, 0xc2e9, 0 },
> +	{ 0xc4db, 0xc4db, 0xc4db, 0 },
> +	{ 0xc6d0, 0xc6d0, 0xc6d0, 0 },
> +	{ 0xc8c8, 0xc8c8, 0xc8c8, 0 },
> +	{ 0xcac3, 0xcac3, 0xcac3, 0 },
> +	{ 0xccc1, 0xccc1, 0xccc1, 0 },
> +	{ 0xcec1, 0xcec1, 0xcec1, 0 },
> +	{ 0xd0c5, 0xd0c5, 0xd0c5, 0 },
> +	{ 0xd2cc, 0xd2cc, 0xd2cc, 0 },
> +	{ 0xd4d5, 0xd4d5, 0xd4d5, 0 },
> +	{ 0xd6e1, 0xd6e1, 0xd6e1, 0 },
> +	{ 0xd8f1, 0xd8f1, 0xd8f1, 0 },
> +	{ 0xdb03, 0xdb03, 0xdb03, 0 },
> +	{ 0xdd18, 0xdd18, 0xdd18, 0 },
> +	{ 0xdf30, 0xdf30, 0xdf30, 0 },
> +	{ 0xe14b, 0xe14b, 0xe14b, 0 },
> +	{ 0xe369, 0xe369, 0xe369, 0 },
> +	{ 0xe58a, 0xe58a, 0xe58a, 0 },
> +	{ 0xe7ae, 0xe7ae, 0xe7ae, 0 },
> +	{ 0xe9d5, 0xe9d5, 0xe9d5, 0 },
> +	{ 0xebff, 0xebff, 0xebff, 0 },
> +	{ 0xee2c, 0xee2c, 0xee2c, 0 },
> +	{ 0xf05c, 0xf05c, 0xf05c, 0 },
> +	{ 0xf28f, 0xf28f, 0xf28f, 0 },
> +	{ 0xf4c4, 0xf4c4, 0xf4c4, 0 },
> +	{ 0xf6fd, 0xf6fd, 0xf6fd, 0 },
> +	{ 0xf939, 0xf939, 0xf939, 0 },
> +	{ 0xfb78, 0xfb78, 0xfb78, 0 },
> +	{ 0xfdba, 0xfdba, 0xfdba, 0 },
> +	{ 0xffff, 0xffff, 0xffff, 0 }
> +};
> +
> +#if 0
> +struct vkms_color_lut srgb_eotf = {
> +	.base = NULL,
> +	. lut_length = LUT_SIZE,
> +	.channel_value2index_ratio = drm_int2fixp(0xffff)
> +	// .channel_value2index_ratio = 0 //drm_fixp_div(drm_int2fixp(0xffff), drm_int2fixp(LUT_SIZE))
> +};
> +
> +#else
> +const struct vkms_color_lut srgb_eotf = {
> +	.base = srgb_array,
> +	.lut_length = 256,
> +	.channel_value2index_ratio = 16711935ll
> +};
> +
> +#endif
> +
>  static u16 pre_mul_blend_channel(u16 src, u16 dst, u16 alpha)
>  {
>  	u32 new_color;
> @@ -136,6 +414,39 @@ static void apply_lut(const struct vkms_crtc_state *crtc_state, struct line_buff
>  	}
>  }
>  
> +static void pre_blend_color_transform(const struct vkms_plane_state *plane_state, struct line_buffer *output_buffer)
> +{
> +	struct drm_colorop *pipeline = plane_state->base.base.color_pipeline;
> +	/* TODO this is probably wrong */
> +	struct drm_colorop_state *colorop_state;
> +
> +	if (!pipeline)
> +		return;
> +
> +	colorop_state = pipeline->state;
> +
> +	if (!colorop_state)
> +		return;
> +
> +	for (size_t x = 0; x < output_buffer->n_pixels; x++) {
> +		struct pixel_argb_u16 *pixel = &output_buffer->pixels[x];
> +
> +		if (pipeline->type == DRM_COLOROP_1D_CURVE &&
> +			colorop_state->bypass == false) {
> +			switch (colorop_state->curve_1d_type) {
> +				case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
> +					break;
> +				case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
> +				default:
> +					pixel->r = apply_lut_to_channel_value(&srgb_eotf, pixel->r, LUT_RED);
> +					pixel->g = apply_lut_to_channel_value(&srgb_eotf, pixel->g, LUT_GREEN);
> +					pixel->b = apply_lut_to_channel_value(&srgb_eotf, pixel->b, LUT_BLUE);
> +					break;
> +			}
> +		}
> +	}
> +}
> +
>  /**
>   * @wb_frame_info: The writeback frame buffer metadata
>   * @crtc_state: The crtc state
> @@ -168,8 +479,13 @@ static void blend(struct vkms_writeback_job *wb,
>  				continue;
>  
>  			plane[i]->plane_read(stage_buffer, plane[i]->frame_info, y);
> +
> +			/* do per-plane color transformations here */
> +			// pre_blend_color_transform(plane[i], stage_buffer);
> +
>  			pre_mul_alpha_blend(plane[i]->frame_info, stage_buffer,
>  					    output_buffer);
> +			pre_blend_color_transform(plane[i], output_buffer);

I see it should be applied to the `stage_buffer` before blending (i.e.
pre_mul_alpha_blend()) and in the lines commented above. Were you
getting any unexpected result?

Otherwise, having this VKMS implementation looks very nice. Thank you!

Melissa

>  		}
>  
>  		apply_lut(crtc_state, output_buffer);
> diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
> index 310b31f47928..c04f714cd486 100644
> --- a/drivers/gpu/drm/vkms/vkms_drv.h
> +++ b/drivers/gpu/drm/vkms/vkms_drv.h
> @@ -168,4 +168,8 @@ void vkms_set_composer(struct vkms_output *out, bool enabled);
>  /* Writeback */
>  int vkms_enable_writeback_connector(struct vkms_device *vkmsdev);
>  
> +/* Colorops */
> +int vkms_initialize_colorops(struct drm_plane *plane);
> +
> +
>  #endif /* _VKMS_DRV_H_ */
> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
> index b3f8a115cc23..cbffbdd7cbf9 100644
> --- a/drivers/gpu/drm/vkms/vkms_plane.c
> +++ b/drivers/gpu/drm/vkms/vkms_plane.c
> @@ -237,5 +237,7 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
>  
>  	drm_plane_helper_add(&plane->base, funcs);
>  
> +	vkms_initialize_colorops(&plane->base);
> +
>  	return plane;
>  }
> -- 
> 2.42.0
>
Harry Wentland Oct. 19, 2023, 3:50 p.m. UTC | #2
On 2023-10-10 12:27, Melissa Wen wrote:
> On 09/08, Harry Wentland wrote:
>> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
>> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>> Cc: Pekka Paalanen <pekka.paalanen@collabora.com>
>> Cc: Simon Ser <contact@emersion.fr>
>> Cc: Harry Wentland <harry.wentland@amd.com>
>> Cc: Melissa Wen <mwen@igalia.com>
>> Cc: Jonas Ådahl <jadahl@redhat.com>
>> Cc: Sebastian Wick <sebastian.wick@redhat.com>
>> Cc: Shashank Sharma <shashank.sharma@amd.com>
>> Cc: Alexander Goins <agoins@nvidia.com>
>> Cc: Joshua Ashton <joshua@froggi.es>
>> Cc: Michel Dänzer <mdaenzer@redhat.com>
>> Cc: Aleix Pol <aleixpol@kde.org>
>> Cc: Xaver Hugl <xaver.hugl@gmail.com>
>> Cc: Victoria Brekenfeld <victoria@system76.com>
>> Cc: Daniel Vetter <daniel@ffwll.ch>
>> Cc: Uma Shankar <uma.shankar@intel.com>
>> Cc: Naseer Ahmed <quic_naseer@quicinc.com>
>> Cc: Christopher Braga <quic_cbraga@quicinc.com>
>> ---
>>  drivers/gpu/drm/vkms/Makefile        |   3 +-
>>  drivers/gpu/drm/vkms/vkms_colorop.c  | 108 +++++++++
>>  drivers/gpu/drm/vkms/vkms_composer.c | 316 +++++++++++++++++++++++++++
>>  drivers/gpu/drm/vkms/vkms_drv.h      |   4 +
>>  drivers/gpu/drm/vkms/vkms_plane.c    |   2 +
>>  5 files changed, 432 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/gpu/drm/vkms/vkms_colorop.c
>>
>> diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
>> index 1b28a6a32948..bcf508873622 100644
>> --- a/drivers/gpu/drm/vkms/Makefile
>> +++ b/drivers/gpu/drm/vkms/Makefile
>> @@ -6,6 +6,7 @@ vkms-y := \
>>  	vkms_formats.o \
>>  	vkms_crtc.o \
>>  	vkms_composer.o \
>> -	vkms_writeback.o
>> +	vkms_writeback.o \
>> +	vkms_colorop.o
>>  
>>  obj-$(CONFIG_DRM_VKMS) += vkms.o
>> diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
>> new file mode 100644
>> index 000000000000..b3da0705bca7
>> --- /dev/null
>> +++ b/drivers/gpu/drm/vkms/vkms_colorop.c
>> @@ -0,0 +1,108 @@
>> +/*
>> + * Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
>> + * OTHER DEALINGS IN THE SOFTWARE.
>> + *
>> + * Authors: AMD
>> + *
>> + */
>> +
>> +#include <linux/slab.h>
>> +#include <drm/drm_colorop.h>
>> +#include <drm/drm_print.h>
>> +#include <drm/drm_property.h>
>> +#include <drm/drm_plane.h>
>> +
>> +#define MAX_COLOR_PIPELINES 5
>> +
>> +const int vkms_initialize_tf_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
>> +{
>> +
>> +	struct drm_colorop *op, *prev_op;
>> +	struct drm_device *dev = plane->dev;
>> +	int ret;
>> +
>> +	/* 1st op: 1d curve */
>> +	op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
>> +	if (!op) {
>> +		DRM_ERROR("KMS: Failed to allocate colorop\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	ret = drm_colorop_init(dev, op, plane, DRM_COLOROP_1D_CURVE);
>> +	if (ret)
>> +		return ret;
>> +
>> +	list->type = op->base.id;
>> +	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", op->base.id);
>> +
>> +	prev_op = op;
>> +
>> +	/* 2nd op: 1d curve */
>> +	op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
>> +	if (!op) {
>> +		DRM_ERROR("KMS: Failed to allocate colorop\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	ret = drm_colorop_init(dev, op, plane, DRM_COLOROP_1D_CURVE);
>> +	if (ret)
>> +		return ret;
>> +
>> +	drm_colorop_set_next_property(prev_op, op);
>> +
>> +	return 0;
>> +}
>> +
>> +int vkms_initialize_colorops(struct drm_plane *plane)
>> +{
>> +	struct drm_device *dev = plane->dev;
>> +	struct drm_property *prop;
>> +	struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>> +	int len = 0;
>> +	int ret;
>> +
>> +	/* Add "Bypass" (i.e. NULL) pipeline */
>> +	pipelines[len].type = 0;
>> +	pipelines[len].name = "Bypass";
>> +	len++;
>> +
>> +	/* Add pipeline consisting of transfer functions */
>> +	ret = vkms_initialize_tf_pipeline(plane, &(pipelines[len]));
>> +	if (ret)
>> +		return ret;
>> +	len++;
>> +
>> +	/* Create COLOR_PIPELINE property and attach */
>> +	prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC,
>> +					"COLOR_PIPELINE",
>> +					pipelines, len);
>> +	if (!prop)
>> +		return -ENOMEM;
>> +
>> +	plane->color_pipeline_property = prop;
>> +
>> +	drm_object_attach_property(&plane->base, prop, 0);
>> +
>> +	/* TODO do we even need this? */
>> +	if (plane->state)
>> +		plane->state->color_pipeline = NULL;
>> +
>> +	return 0;
>> +}
>> diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
>> index f6c311e8a87c..92ab9c62a554 100644
>> --- a/drivers/gpu/drm/vkms/vkms_composer.c
>> +++ b/drivers/gpu/drm/vkms/vkms_composer.c
>> @@ -12,6 +12,284 @@
>>  
>>  #include "vkms_drv.h"
>>  
>> +#define LUT_SIZE 256
>> +
>> +struct drm_color_lut srgb_array[LUT_SIZE] = {
>> +	{ 0x13, 0x13, 0x13, 0 },
>> +	{ 0x27, 0x27, 0x27, 0 },
>> +	{ 0x3b, 0x3b, 0x3b, 0 },
>> +	{ 0x4f, 0x4f, 0x4f, 0 },
>> +	{ 0x63, 0x63, 0x63, 0 },
>> +	{ 0x76, 0x76, 0x76, 0 },
>> +	{ 0x8a, 0x8a, 0x8a, 0 },
>> +	{ 0x9e, 0x9e, 0x9e, 0 },
>> +	{ 0xb2, 0xb2, 0xb2, 0 },
>> +	{ 0xc6, 0xc6, 0xc6, 0 },
>> +	{ 0xda, 0xda, 0xda, 0 },
>> +	{ 0xef, 0xef, 0xef, 0 },
>> +	{ 0x106, 0x106, 0x106, 0 },
>> +	{ 0x11e, 0x11e, 0x11e, 0 },
>> +	{ 0x137, 0x137, 0x137, 0 },
>> +	{ 0x151, 0x151, 0x151, 0 },
>> +	{ 0x16d, 0x16d, 0x16d, 0 },
>> +	{ 0x18a, 0x18a, 0x18a, 0 },
>> +	{ 0x1a8, 0x1a8, 0x1a8, 0 },
>> +	{ 0x1c7, 0x1c7, 0x1c7, 0 },
>> +	{ 0x1e8, 0x1e8, 0x1e8, 0 },
>> +	{ 0x20a, 0x20a, 0x20a, 0 },
>> +	{ 0x22e, 0x22e, 0x22e, 0 },
>> +	{ 0x253, 0x253, 0x253, 0 },
>> +	{ 0x279, 0x279, 0x279, 0 },
>> +	{ 0x2a0, 0x2a0, 0x2a0, 0 },
>> +	{ 0x2c9, 0x2c9, 0x2c9, 0 },
>> +	{ 0x2f4, 0x2f4, 0x2f4, 0 },
>> +	{ 0x320, 0x320, 0x320, 0 },
>> +	{ 0x34d, 0x34d, 0x34d, 0 },
>> +	{ 0x37c, 0x37c, 0x37c, 0 },
>> +	{ 0x3ac, 0x3ac, 0x3ac, 0 },
>> +	{ 0x3de, 0x3de, 0x3de, 0 },
>> +	{ 0x411, 0x411, 0x411, 0 },
>> +	{ 0x446, 0x446, 0x446, 0 },
>> +	{ 0x47c, 0x47c, 0x47c, 0 },
>> +	{ 0x4b4, 0x4b4, 0x4b4, 0 },
>> +	{ 0x4ed, 0x4ed, 0x4ed, 0 },
>> +	{ 0x528, 0x528, 0x528, 0 },
>> +	{ 0x564, 0x564, 0x564, 0 },
>> +	{ 0x5a3, 0x5a3, 0x5a3, 0 },
>> +	{ 0x5e2, 0x5e2, 0x5e2, 0 },
>> +	{ 0x624, 0x624, 0x624, 0 },
>> +	{ 0x666, 0x666, 0x666, 0 },
>> +	{ 0x6ab, 0x6ab, 0x6ab, 0 },
>> +	{ 0x6f1, 0x6f1, 0x6f1, 0 },
>> +	{ 0x739, 0x739, 0x739, 0 },
>> +	{ 0x782, 0x782, 0x782, 0 },
>> +	{ 0x7ce, 0x7ce, 0x7ce, 0 },
>> +	{ 0x81b, 0x81b, 0x81b, 0 },
>> +	{ 0x869, 0x869, 0x869, 0 },
>> +	{ 0x8b9, 0x8b9, 0x8b9, 0 },
>> +	{ 0x90b, 0x90b, 0x90b, 0 },
>> +	{ 0x95f, 0x95f, 0x95f, 0 },
>> +	{ 0x9b5, 0x9b5, 0x9b5, 0 },
>> +	{ 0xa0c, 0xa0c, 0xa0c, 0 },
>> +	{ 0xa65, 0xa65, 0xa65, 0 },
>> +	{ 0xabf, 0xabf, 0xabf, 0 },
>> +	{ 0xb1c, 0xb1c, 0xb1c, 0 },
>> +	{ 0xb7a, 0xb7a, 0xb7a, 0 },
>> +	{ 0xbda, 0xbda, 0xbda, 0 },
>> +	{ 0xc3c, 0xc3c, 0xc3c, 0 },
>> +	{ 0xca0, 0xca0, 0xca0, 0 },
>> +	{ 0xd06, 0xd06, 0xd06, 0 },
>> +	{ 0xd6d, 0xd6d, 0xd6d, 0 },
>> +	{ 0xdd6, 0xdd6, 0xdd6, 0 },
>> +	{ 0xe41, 0xe41, 0xe41, 0 },
>> +	{ 0xeae, 0xeae, 0xeae, 0 },
>> +	{ 0xf1d, 0xf1d, 0xf1d, 0 },
>> +	{ 0xf8e, 0xf8e, 0xf8e, 0 },
>> +	{ 0x1001, 0x1001, 0x1001, 0 },
>> +	{ 0x1075, 0x1075, 0x1075, 0 },
>> +	{ 0x10ec, 0x10ec, 0x10ec, 0 },
>> +	{ 0x1164, 0x1164, 0x1164, 0 },
>> +	{ 0x11de, 0x11de, 0x11de, 0 },
>> +	{ 0x125a, 0x125a, 0x125a, 0 },
>> +	{ 0x12d9, 0x12d9, 0x12d9, 0 },
>> +	{ 0x1359, 0x1359, 0x1359, 0 },
>> +	{ 0x13db, 0x13db, 0x13db, 0 },
>> +	{ 0x145f, 0x145f, 0x145f, 0 },
>> +	{ 0x14e5, 0x14e5, 0x14e5, 0 },
>> +	{ 0x156d, 0x156d, 0x156d, 0 },
>> +	{ 0x15f7, 0x15f7, 0x15f7, 0 },
>> +	{ 0x1683, 0x1683, 0x1683, 0 },
>> +	{ 0x1711, 0x1711, 0x1711, 0 },
>> +	{ 0x17a1, 0x17a1, 0x17a1, 0 },
>> +	{ 0x1833, 0x1833, 0x1833, 0 },
>> +	{ 0x18c7, 0x18c7, 0x18c7, 0 },
>> +	{ 0x195d, 0x195d, 0x195d, 0 },
>> +	{ 0x19f6, 0x19f6, 0x19f6, 0 },
>> +	{ 0x1a90, 0x1a90, 0x1a90, 0 },
>> +	{ 0x1b2c, 0x1b2c, 0x1b2c, 0 },
>> +	{ 0x1bcb, 0x1bcb, 0x1bcb, 0 },
>> +	{ 0x1c6b, 0x1c6b, 0x1c6b, 0 },
>> +	{ 0x1d0e, 0x1d0e, 0x1d0e, 0 },
>> +	{ 0x1db3, 0x1db3, 0x1db3, 0 },
>> +	{ 0x1e59, 0x1e59, 0x1e59, 0 },
>> +	{ 0x1f02, 0x1f02, 0x1f02, 0 },
>> +	{ 0x1fad, 0x1fad, 0x1fad, 0 },
>> +	{ 0x205b, 0x205b, 0x205b, 0 },
>> +	{ 0x210a, 0x210a, 0x210a, 0 },
>> +	{ 0x21bb, 0x21bb, 0x21bb, 0 },
>> +	{ 0x226f, 0x226f, 0x226f, 0 },
>> +	{ 0x2325, 0x2325, 0x2325, 0 },
>> +	{ 0x23dd, 0x23dd, 0x23dd, 0 },
>> +	{ 0x2497, 0x2497, 0x2497, 0 },
>> +	{ 0x2553, 0x2553, 0x2553, 0 },
>> +	{ 0x2612, 0x2612, 0x2612, 0 },
>> +	{ 0x26d2, 0x26d2, 0x26d2, 0 },
>> +	{ 0x2795, 0x2795, 0x2795, 0 },
>> +	{ 0x285a, 0x285a, 0x285a, 0 },
>> +	{ 0x2922, 0x2922, 0x2922, 0 },
>> +	{ 0x29eb, 0x29eb, 0x29eb, 0 },
>> +	{ 0x2ab7, 0x2ab7, 0x2ab7, 0 },
>> +	{ 0x2b85, 0x2b85, 0x2b85, 0 },
>> +	{ 0x2c56, 0x2c56, 0x2c56, 0 },
>> +	{ 0x2d28, 0x2d28, 0x2d28, 0 },
>> +	{ 0x2dfd, 0x2dfd, 0x2dfd, 0 },
>> +	{ 0x2ed4, 0x2ed4, 0x2ed4, 0 },
>> +	{ 0x2fad, 0x2fad, 0x2fad, 0 },
>> +	{ 0x3089, 0x3089, 0x3089, 0 },
>> +	{ 0x3167, 0x3167, 0x3167, 0 },
>> +	{ 0x3247, 0x3247, 0x3247, 0 },
>> +	{ 0x332a, 0x332a, 0x332a, 0 },
>> +	{ 0x340e, 0x340e, 0x340e, 0 },
>> +	{ 0x34f5, 0x34f5, 0x34f5, 0 },
>> +	{ 0x35df, 0x35df, 0x35df, 0 },
>> +	{ 0x36cb, 0x36cb, 0x36cb, 0 },
>> +	{ 0x37b9, 0x37b9, 0x37b9, 0 },
>> +	{ 0x38a9, 0x38a9, 0x38a9, 0 },
>> +	{ 0x399c, 0x399c, 0x399c, 0 },
>> +	{ 0x3a91, 0x3a91, 0x3a91, 0 },
>> +	{ 0x3b89, 0x3b89, 0x3b89, 0 },
>> +	{ 0x3c83, 0x3c83, 0x3c83, 0 },
>> +	{ 0x3d7f, 0x3d7f, 0x3d7f, 0 },
>> +	{ 0x3e7e, 0x3e7e, 0x3e7e, 0 },
>> +	{ 0x3f7f, 0x3f7f, 0x3f7f, 0 },
>> +	{ 0x4082, 0x4082, 0x4082, 0 },
>> +	{ 0x4188, 0x4188, 0x4188, 0 },
>> +	{ 0x4290, 0x4290, 0x4290, 0 },
>> +	{ 0x439b, 0x439b, 0x439b, 0 },
>> +	{ 0x44a8, 0x44a8, 0x44a8, 0 },
>> +	{ 0x45b7, 0x45b7, 0x45b7, 0 },
>> +	{ 0x46c9, 0x46c9, 0x46c9, 0 },
>> +	{ 0x47dd, 0x47dd, 0x47dd, 0 },
>> +	{ 0x48f4, 0x48f4, 0x48f4, 0 },
>> +	{ 0x4a0d, 0x4a0d, 0x4a0d, 0 },
>> +	{ 0x4b29, 0x4b29, 0x4b29, 0 },
>> +	{ 0x4c47, 0x4c47, 0x4c47, 0 },
>> +	{ 0x4d68, 0x4d68, 0x4d68, 0 },
>> +	{ 0x4e8b, 0x4e8b, 0x4e8b, 0 },
>> +	{ 0x4fb1, 0x4fb1, 0x4fb1, 0 },
>> +	{ 0x50d9, 0x50d9, 0x50d9, 0 },
>> +	{ 0x5203, 0x5203, 0x5203, 0 },
>> +	{ 0x5330, 0x5330, 0x5330, 0 },
>> +	{ 0x5460, 0x5460, 0x5460, 0 },
>> +	{ 0x5592, 0x5592, 0x5592, 0 },
>> +	{ 0x56c6, 0x56c6, 0x56c6, 0 },
>> +	{ 0x57fd, 0x57fd, 0x57fd, 0 },
>> +	{ 0x5937, 0x5937, 0x5937, 0 },
>> +	{ 0x5a73, 0x5a73, 0x5a73, 0 },
>> +	{ 0x5bb2, 0x5bb2, 0x5bb2, 0 },
>> +	{ 0x5cf3, 0x5cf3, 0x5cf3, 0 },
>> +	{ 0x5e37, 0x5e37, 0x5e37, 0 },
>> +	{ 0x5f7d, 0x5f7d, 0x5f7d, 0 },
>> +	{ 0x60c6, 0x60c6, 0x60c6, 0 },
>> +	{ 0x6212, 0x6212, 0x6212, 0 },
>> +	{ 0x6360, 0x6360, 0x6360, 0 },
>> +	{ 0x64b0, 0x64b0, 0x64b0, 0 },
>> +	{ 0x6604, 0x6604, 0x6604, 0 },
>> +	{ 0x6759, 0x6759, 0x6759, 0 },
>> +	{ 0x68b2, 0x68b2, 0x68b2, 0 },
>> +	{ 0x6a0d, 0x6a0d, 0x6a0d, 0 },
>> +	{ 0x6b6a, 0x6b6a, 0x6b6a, 0 },
>> +	{ 0x6ccb, 0x6ccb, 0x6ccb, 0 },
>> +	{ 0x6e2d, 0x6e2d, 0x6e2d, 0 },
>> +	{ 0x6f93, 0x6f93, 0x6f93, 0 },
>> +	{ 0x70fb, 0x70fb, 0x70fb, 0 },
>> +	{ 0x7266, 0x7266, 0x7266, 0 },
>> +	{ 0x73d3, 0x73d3, 0x73d3, 0 },
>> +	{ 0x7543, 0x7543, 0x7543, 0 },
>> +	{ 0x76b6, 0x76b6, 0x76b6, 0 },
>> +	{ 0x782b, 0x782b, 0x782b, 0 },
>> +	{ 0x79a3, 0x79a3, 0x79a3, 0 },
>> +	{ 0x7b1d, 0x7b1d, 0x7b1d, 0 },
>> +	{ 0x7c9b, 0x7c9b, 0x7c9b, 0 },
>> +	{ 0x7e1b, 0x7e1b, 0x7e1b, 0 },
>> +	{ 0x7f9d, 0x7f9d, 0x7f9d, 0 },
>> +	{ 0x8123, 0x8123, 0x8123, 0 },
>> +	{ 0x82ab, 0x82ab, 0x82ab, 0 },
>> +	{ 0x8436, 0x8436, 0x8436, 0 },
>> +	{ 0x85c3, 0x85c3, 0x85c3, 0 },
>> +	{ 0x8753, 0x8753, 0x8753, 0 },
>> +	{ 0x88e6, 0x88e6, 0x88e6, 0 },
>> +	{ 0x8a7c, 0x8a7c, 0x8a7c, 0 },
>> +	{ 0x8c14, 0x8c14, 0x8c14, 0 },
>> +	{ 0x8daf, 0x8daf, 0x8daf, 0 },
>> +	{ 0x8f4d, 0x8f4d, 0x8f4d, 0 },
>> +	{ 0x90ed, 0x90ed, 0x90ed, 0 },
>> +	{ 0x9290, 0x9290, 0x9290, 0 },
>> +	{ 0x9436, 0x9436, 0x9436, 0 },
>> +	{ 0x95df, 0x95df, 0x95df, 0 },
>> +	{ 0x978b, 0x978b, 0x978b, 0 },
>> +	{ 0x9939, 0x9939, 0x9939, 0 },
>> +	{ 0x9aea, 0x9aea, 0x9aea, 0 },
>> +	{ 0x9c9e, 0x9c9e, 0x9c9e, 0 },
>> +	{ 0x9e55, 0x9e55, 0x9e55, 0 },
>> +	{ 0xa00e, 0xa00e, 0xa00e, 0 },
>> +	{ 0xa1ca, 0xa1ca, 0xa1ca, 0 },
>> +	{ 0xa389, 0xa389, 0xa389, 0 },
>> +	{ 0xa54b, 0xa54b, 0xa54b, 0 },
>> +	{ 0xa710, 0xa710, 0xa710, 0 },
>> +	{ 0xa8d7, 0xa8d7, 0xa8d7, 0 },
>> +	{ 0xaaa1, 0xaaa1, 0xaaa1, 0 },
>> +	{ 0xac6e, 0xac6e, 0xac6e, 0 },
>> +	{ 0xae3e, 0xae3e, 0xae3e, 0 },
>> +	{ 0xb011, 0xb011, 0xb011, 0 },
>> +	{ 0xb1e7, 0xb1e7, 0xb1e7, 0 },
>> +	{ 0xb3bf, 0xb3bf, 0xb3bf, 0 },
>> +	{ 0xb59a, 0xb59a, 0xb59a, 0 },
>> +	{ 0xb778, 0xb778, 0xb778, 0 },
>> +	{ 0xb959, 0xb959, 0xb959, 0 },
>> +	{ 0xbb3d, 0xbb3d, 0xbb3d, 0 },
>> +	{ 0xbd24, 0xbd24, 0xbd24, 0 },
>> +	{ 0xbf0d, 0xbf0d, 0xbf0d, 0 },
>> +	{ 0xc0fa, 0xc0fa, 0xc0fa, 0 },
>> +	{ 0xc2e9, 0xc2e9, 0xc2e9, 0 },
>> +	{ 0xc4db, 0xc4db, 0xc4db, 0 },
>> +	{ 0xc6d0, 0xc6d0, 0xc6d0, 0 },
>> +	{ 0xc8c8, 0xc8c8, 0xc8c8, 0 },
>> +	{ 0xcac3, 0xcac3, 0xcac3, 0 },
>> +	{ 0xccc1, 0xccc1, 0xccc1, 0 },
>> +	{ 0xcec1, 0xcec1, 0xcec1, 0 },
>> +	{ 0xd0c5, 0xd0c5, 0xd0c5, 0 },
>> +	{ 0xd2cc, 0xd2cc, 0xd2cc, 0 },
>> +	{ 0xd4d5, 0xd4d5, 0xd4d5, 0 },
>> +	{ 0xd6e1, 0xd6e1, 0xd6e1, 0 },
>> +	{ 0xd8f1, 0xd8f1, 0xd8f1, 0 },
>> +	{ 0xdb03, 0xdb03, 0xdb03, 0 },
>> +	{ 0xdd18, 0xdd18, 0xdd18, 0 },
>> +	{ 0xdf30, 0xdf30, 0xdf30, 0 },
>> +	{ 0xe14b, 0xe14b, 0xe14b, 0 },
>> +	{ 0xe369, 0xe369, 0xe369, 0 },
>> +	{ 0xe58a, 0xe58a, 0xe58a, 0 },
>> +	{ 0xe7ae, 0xe7ae, 0xe7ae, 0 },
>> +	{ 0xe9d5, 0xe9d5, 0xe9d5, 0 },
>> +	{ 0xebff, 0xebff, 0xebff, 0 },
>> +	{ 0xee2c, 0xee2c, 0xee2c, 0 },
>> +	{ 0xf05c, 0xf05c, 0xf05c, 0 },
>> +	{ 0xf28f, 0xf28f, 0xf28f, 0 },
>> +	{ 0xf4c4, 0xf4c4, 0xf4c4, 0 },
>> +	{ 0xf6fd, 0xf6fd, 0xf6fd, 0 },
>> +	{ 0xf939, 0xf939, 0xf939, 0 },
>> +	{ 0xfb78, 0xfb78, 0xfb78, 0 },
>> +	{ 0xfdba, 0xfdba, 0xfdba, 0 },
>> +	{ 0xffff, 0xffff, 0xffff, 0 }
>> +};
>> +
>> +#if 0
>> +struct vkms_color_lut srgb_eotf = {
>> +	.base = NULL,
>> +	. lut_length = LUT_SIZE,
>> +	.channel_value2index_ratio = drm_int2fixp(0xffff)
>> +	// .channel_value2index_ratio = 0 //drm_fixp_div(drm_int2fixp(0xffff), drm_int2fixp(LUT_SIZE))
>> +};
>> +
>> +#else
>> +const struct vkms_color_lut srgb_eotf = {
>> +	.base = srgb_array,
>> +	.lut_length = 256,
>> +	.channel_value2index_ratio = 16711935ll
>> +};
>> +
>> +#endif
>> +
>>  static u16 pre_mul_blend_channel(u16 src, u16 dst, u16 alpha)
>>  {
>>  	u32 new_color;
>> @@ -136,6 +414,39 @@ static void apply_lut(const struct vkms_crtc_state *crtc_state, struct line_buff
>>  	}
>>  }
>>  
>> +static void pre_blend_color_transform(const struct vkms_plane_state *plane_state, struct line_buffer *output_buffer)
>> +{
>> +	struct drm_colorop *pipeline = plane_state->base.base.color_pipeline;
>> +	/* TODO this is probably wrong */
>> +	struct drm_colorop_state *colorop_state;
>> +
>> +	if (!pipeline)
>> +		return;
>> +
>> +	colorop_state = pipeline->state;
>> +
>> +	if (!colorop_state)
>> +		return;
>> +
>> +	for (size_t x = 0; x < output_buffer->n_pixels; x++) {
>> +		struct pixel_argb_u16 *pixel = &output_buffer->pixels[x];
>> +
>> +		if (pipeline->type == DRM_COLOROP_1D_CURVE &&
>> +			colorop_state->bypass == false) {
>> +			switch (colorop_state->curve_1d_type) {
>> +				case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
>> +					break;
>> +				case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
>> +				default:
>> +					pixel->r = apply_lut_to_channel_value(&srgb_eotf, pixel->r, LUT_RED);
>> +					pixel->g = apply_lut_to_channel_value(&srgb_eotf, pixel->g, LUT_GREEN);
>> +					pixel->b = apply_lut_to_channel_value(&srgb_eotf, pixel->b, LUT_BLUE);
>> +					break;
>> +			}
>> +		}
>> +	}
>> +}
>> +
>>  /**
>>   * @wb_frame_info: The writeback frame buffer metadata
>>   * @crtc_state: The crtc state
>> @@ -168,8 +479,13 @@ static void blend(struct vkms_writeback_job *wb,
>>  				continue;
>>  
>>  			plane[i]->plane_read(stage_buffer, plane[i]->frame_info, y);
>> +
>> +			/* do per-plane color transformations here */
>> +			// pre_blend_color_transform(plane[i], stage_buffer);
>> +
>>  			pre_mul_alpha_blend(plane[i]->frame_info, stage_buffer,
>>  					    output_buffer);
>> +			pre_blend_color_transform(plane[i], output_buffer);
> 
> I see it should be applied to the `stage_buffer` before blending (i.e.
> pre_mul_alpha_blend()) and in the lines commented above. Were you
> getting any unexpected result?
> 

v2 fixes this. You're absolutely right. I did see some issues and was
experimenting with moving things around, but it needs to be before the
blend call.

> Otherwise, having this VKMS implementation looks very nice. Thank you!
> 

Thanks :)
Harry

> Melissa
> 
>>  		}
>>  
>>  		apply_lut(crtc_state, output_buffer);
>> diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
>> index 310b31f47928..c04f714cd486 100644
>> --- a/drivers/gpu/drm/vkms/vkms_drv.h
>> +++ b/drivers/gpu/drm/vkms/vkms_drv.h
>> @@ -168,4 +168,8 @@ void vkms_set_composer(struct vkms_output *out, bool enabled);
>>  /* Writeback */
>>  int vkms_enable_writeback_connector(struct vkms_device *vkmsdev);
>>  
>> +/* Colorops */
>> +int vkms_initialize_colorops(struct drm_plane *plane);
>> +
>> +
>>  #endif /* _VKMS_DRV_H_ */
>> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
>> index b3f8a115cc23..cbffbdd7cbf9 100644
>> --- a/drivers/gpu/drm/vkms/vkms_plane.c
>> +++ b/drivers/gpu/drm/vkms/vkms_plane.c
>> @@ -237,5 +237,7 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
>>  
>>  	drm_plane_helper_add(&plane->base, funcs);
>>  
>> +	vkms_initialize_colorops(&plane->base);
>> +
>>  	return plane;
>>  }
>> -- 
>> 2.42.0
>>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
index 1b28a6a32948..bcf508873622 100644
--- a/drivers/gpu/drm/vkms/Makefile
+++ b/drivers/gpu/drm/vkms/Makefile
@@ -6,6 +6,7 @@  vkms-y := \
 	vkms_formats.o \
 	vkms_crtc.o \
 	vkms_composer.o \
-	vkms_writeback.o
+	vkms_writeback.o \
+	vkms_colorop.o
 
 obj-$(CONFIG_DRM_VKMS) += vkms.o
diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
new file mode 100644
index 000000000000..b3da0705bca7
--- /dev/null
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -0,0 +1,108 @@ 
+/*
+ * Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/slab.h>
+#include <drm/drm_colorop.h>
+#include <drm/drm_print.h>
+#include <drm/drm_property.h>
+#include <drm/drm_plane.h>
+
+#define MAX_COLOR_PIPELINES 5
+
+const int vkms_initialize_tf_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
+{
+
+	struct drm_colorop *op, *prev_op;
+	struct drm_device *dev = plane->dev;
+	int ret;
+
+	/* 1st op: 1d curve */
+	op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+	if (!op) {
+		DRM_ERROR("KMS: Failed to allocate colorop\n");
+		return -ENOMEM;
+	}
+
+	ret = drm_colorop_init(dev, op, plane, DRM_COLOROP_1D_CURVE);
+	if (ret)
+		return ret;
+
+	list->type = op->base.id;
+	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", op->base.id);
+
+	prev_op = op;
+
+	/* 2nd op: 1d curve */
+	op = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+	if (!op) {
+		DRM_ERROR("KMS: Failed to allocate colorop\n");
+		return -ENOMEM;
+	}
+
+	ret = drm_colorop_init(dev, op, plane, DRM_COLOROP_1D_CURVE);
+	if (ret)
+		return ret;
+
+	drm_colorop_set_next_property(prev_op, op);
+
+	return 0;
+}
+
+int vkms_initialize_colorops(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_property *prop;
+	struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
+	int len = 0;
+	int ret;
+
+	/* Add "Bypass" (i.e. NULL) pipeline */
+	pipelines[len].type = 0;
+	pipelines[len].name = "Bypass";
+	len++;
+
+	/* Add pipeline consisting of transfer functions */
+	ret = vkms_initialize_tf_pipeline(plane, &(pipelines[len]));
+	if (ret)
+		return ret;
+	len++;
+
+	/* Create COLOR_PIPELINE property and attach */
+	prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC,
+					"COLOR_PIPELINE",
+					pipelines, len);
+	if (!prop)
+		return -ENOMEM;
+
+	plane->color_pipeline_property = prop;
+
+	drm_object_attach_property(&plane->base, prop, 0);
+
+	/* TODO do we even need this? */
+	if (plane->state)
+		plane->state->color_pipeline = NULL;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index f6c311e8a87c..92ab9c62a554 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -12,6 +12,284 @@ 
 
 #include "vkms_drv.h"
 
+#define LUT_SIZE 256
+
+struct drm_color_lut srgb_array[LUT_SIZE] = {
+	{ 0x13, 0x13, 0x13, 0 },
+	{ 0x27, 0x27, 0x27, 0 },
+	{ 0x3b, 0x3b, 0x3b, 0 },
+	{ 0x4f, 0x4f, 0x4f, 0 },
+	{ 0x63, 0x63, 0x63, 0 },
+	{ 0x76, 0x76, 0x76, 0 },
+	{ 0x8a, 0x8a, 0x8a, 0 },
+	{ 0x9e, 0x9e, 0x9e, 0 },
+	{ 0xb2, 0xb2, 0xb2, 0 },
+	{ 0xc6, 0xc6, 0xc6, 0 },
+	{ 0xda, 0xda, 0xda, 0 },
+	{ 0xef, 0xef, 0xef, 0 },
+	{ 0x106, 0x106, 0x106, 0 },
+	{ 0x11e, 0x11e, 0x11e, 0 },
+	{ 0x137, 0x137, 0x137, 0 },
+	{ 0x151, 0x151, 0x151, 0 },
+	{ 0x16d, 0x16d, 0x16d, 0 },
+	{ 0x18a, 0x18a, 0x18a, 0 },
+	{ 0x1a8, 0x1a8, 0x1a8, 0 },
+	{ 0x1c7, 0x1c7, 0x1c7, 0 },
+	{ 0x1e8, 0x1e8, 0x1e8, 0 },
+	{ 0x20a, 0x20a, 0x20a, 0 },
+	{ 0x22e, 0x22e, 0x22e, 0 },
+	{ 0x253, 0x253, 0x253, 0 },
+	{ 0x279, 0x279, 0x279, 0 },
+	{ 0x2a0, 0x2a0, 0x2a0, 0 },
+	{ 0x2c9, 0x2c9, 0x2c9, 0 },
+	{ 0x2f4, 0x2f4, 0x2f4, 0 },
+	{ 0x320, 0x320, 0x320, 0 },
+	{ 0x34d, 0x34d, 0x34d, 0 },
+	{ 0x37c, 0x37c, 0x37c, 0 },
+	{ 0x3ac, 0x3ac, 0x3ac, 0 },
+	{ 0x3de, 0x3de, 0x3de, 0 },
+	{ 0x411, 0x411, 0x411, 0 },
+	{ 0x446, 0x446, 0x446, 0 },
+	{ 0x47c, 0x47c, 0x47c, 0 },
+	{ 0x4b4, 0x4b4, 0x4b4, 0 },
+	{ 0x4ed, 0x4ed, 0x4ed, 0 },
+	{ 0x528, 0x528, 0x528, 0 },
+	{ 0x564, 0x564, 0x564, 0 },
+	{ 0x5a3, 0x5a3, 0x5a3, 0 },
+	{ 0x5e2, 0x5e2, 0x5e2, 0 },
+	{ 0x624, 0x624, 0x624, 0 },
+	{ 0x666, 0x666, 0x666, 0 },
+	{ 0x6ab, 0x6ab, 0x6ab, 0 },
+	{ 0x6f1, 0x6f1, 0x6f1, 0 },
+	{ 0x739, 0x739, 0x739, 0 },
+	{ 0x782, 0x782, 0x782, 0 },
+	{ 0x7ce, 0x7ce, 0x7ce, 0 },
+	{ 0x81b, 0x81b, 0x81b, 0 },
+	{ 0x869, 0x869, 0x869, 0 },
+	{ 0x8b9, 0x8b9, 0x8b9, 0 },
+	{ 0x90b, 0x90b, 0x90b, 0 },
+	{ 0x95f, 0x95f, 0x95f, 0 },
+	{ 0x9b5, 0x9b5, 0x9b5, 0 },
+	{ 0xa0c, 0xa0c, 0xa0c, 0 },
+	{ 0xa65, 0xa65, 0xa65, 0 },
+	{ 0xabf, 0xabf, 0xabf, 0 },
+	{ 0xb1c, 0xb1c, 0xb1c, 0 },
+	{ 0xb7a, 0xb7a, 0xb7a, 0 },
+	{ 0xbda, 0xbda, 0xbda, 0 },
+	{ 0xc3c, 0xc3c, 0xc3c, 0 },
+	{ 0xca0, 0xca0, 0xca0, 0 },
+	{ 0xd06, 0xd06, 0xd06, 0 },
+	{ 0xd6d, 0xd6d, 0xd6d, 0 },
+	{ 0xdd6, 0xdd6, 0xdd6, 0 },
+	{ 0xe41, 0xe41, 0xe41, 0 },
+	{ 0xeae, 0xeae, 0xeae, 0 },
+	{ 0xf1d, 0xf1d, 0xf1d, 0 },
+	{ 0xf8e, 0xf8e, 0xf8e, 0 },
+	{ 0x1001, 0x1001, 0x1001, 0 },
+	{ 0x1075, 0x1075, 0x1075, 0 },
+	{ 0x10ec, 0x10ec, 0x10ec, 0 },
+	{ 0x1164, 0x1164, 0x1164, 0 },
+	{ 0x11de, 0x11de, 0x11de, 0 },
+	{ 0x125a, 0x125a, 0x125a, 0 },
+	{ 0x12d9, 0x12d9, 0x12d9, 0 },
+	{ 0x1359, 0x1359, 0x1359, 0 },
+	{ 0x13db, 0x13db, 0x13db, 0 },
+	{ 0x145f, 0x145f, 0x145f, 0 },
+	{ 0x14e5, 0x14e5, 0x14e5, 0 },
+	{ 0x156d, 0x156d, 0x156d, 0 },
+	{ 0x15f7, 0x15f7, 0x15f7, 0 },
+	{ 0x1683, 0x1683, 0x1683, 0 },
+	{ 0x1711, 0x1711, 0x1711, 0 },
+	{ 0x17a1, 0x17a1, 0x17a1, 0 },
+	{ 0x1833, 0x1833, 0x1833, 0 },
+	{ 0x18c7, 0x18c7, 0x18c7, 0 },
+	{ 0x195d, 0x195d, 0x195d, 0 },
+	{ 0x19f6, 0x19f6, 0x19f6, 0 },
+	{ 0x1a90, 0x1a90, 0x1a90, 0 },
+	{ 0x1b2c, 0x1b2c, 0x1b2c, 0 },
+	{ 0x1bcb, 0x1bcb, 0x1bcb, 0 },
+	{ 0x1c6b, 0x1c6b, 0x1c6b, 0 },
+	{ 0x1d0e, 0x1d0e, 0x1d0e, 0 },
+	{ 0x1db3, 0x1db3, 0x1db3, 0 },
+	{ 0x1e59, 0x1e59, 0x1e59, 0 },
+	{ 0x1f02, 0x1f02, 0x1f02, 0 },
+	{ 0x1fad, 0x1fad, 0x1fad, 0 },
+	{ 0x205b, 0x205b, 0x205b, 0 },
+	{ 0x210a, 0x210a, 0x210a, 0 },
+	{ 0x21bb, 0x21bb, 0x21bb, 0 },
+	{ 0x226f, 0x226f, 0x226f, 0 },
+	{ 0x2325, 0x2325, 0x2325, 0 },
+	{ 0x23dd, 0x23dd, 0x23dd, 0 },
+	{ 0x2497, 0x2497, 0x2497, 0 },
+	{ 0x2553, 0x2553, 0x2553, 0 },
+	{ 0x2612, 0x2612, 0x2612, 0 },
+	{ 0x26d2, 0x26d2, 0x26d2, 0 },
+	{ 0x2795, 0x2795, 0x2795, 0 },
+	{ 0x285a, 0x285a, 0x285a, 0 },
+	{ 0x2922, 0x2922, 0x2922, 0 },
+	{ 0x29eb, 0x29eb, 0x29eb, 0 },
+	{ 0x2ab7, 0x2ab7, 0x2ab7, 0 },
+	{ 0x2b85, 0x2b85, 0x2b85, 0 },
+	{ 0x2c56, 0x2c56, 0x2c56, 0 },
+	{ 0x2d28, 0x2d28, 0x2d28, 0 },
+	{ 0x2dfd, 0x2dfd, 0x2dfd, 0 },
+	{ 0x2ed4, 0x2ed4, 0x2ed4, 0 },
+	{ 0x2fad, 0x2fad, 0x2fad, 0 },
+	{ 0x3089, 0x3089, 0x3089, 0 },
+	{ 0x3167, 0x3167, 0x3167, 0 },
+	{ 0x3247, 0x3247, 0x3247, 0 },
+	{ 0x332a, 0x332a, 0x332a, 0 },
+	{ 0x340e, 0x340e, 0x340e, 0 },
+	{ 0x34f5, 0x34f5, 0x34f5, 0 },
+	{ 0x35df, 0x35df, 0x35df, 0 },
+	{ 0x36cb, 0x36cb, 0x36cb, 0 },
+	{ 0x37b9, 0x37b9, 0x37b9, 0 },
+	{ 0x38a9, 0x38a9, 0x38a9, 0 },
+	{ 0x399c, 0x399c, 0x399c, 0 },
+	{ 0x3a91, 0x3a91, 0x3a91, 0 },
+	{ 0x3b89, 0x3b89, 0x3b89, 0 },
+	{ 0x3c83, 0x3c83, 0x3c83, 0 },
+	{ 0x3d7f, 0x3d7f, 0x3d7f, 0 },
+	{ 0x3e7e, 0x3e7e, 0x3e7e, 0 },
+	{ 0x3f7f, 0x3f7f, 0x3f7f, 0 },
+	{ 0x4082, 0x4082, 0x4082, 0 },
+	{ 0x4188, 0x4188, 0x4188, 0 },
+	{ 0x4290, 0x4290, 0x4290, 0 },
+	{ 0x439b, 0x439b, 0x439b, 0 },
+	{ 0x44a8, 0x44a8, 0x44a8, 0 },
+	{ 0x45b7, 0x45b7, 0x45b7, 0 },
+	{ 0x46c9, 0x46c9, 0x46c9, 0 },
+	{ 0x47dd, 0x47dd, 0x47dd, 0 },
+	{ 0x48f4, 0x48f4, 0x48f4, 0 },
+	{ 0x4a0d, 0x4a0d, 0x4a0d, 0 },
+	{ 0x4b29, 0x4b29, 0x4b29, 0 },
+	{ 0x4c47, 0x4c47, 0x4c47, 0 },
+	{ 0x4d68, 0x4d68, 0x4d68, 0 },
+	{ 0x4e8b, 0x4e8b, 0x4e8b, 0 },
+	{ 0x4fb1, 0x4fb1, 0x4fb1, 0 },
+	{ 0x50d9, 0x50d9, 0x50d9, 0 },
+	{ 0x5203, 0x5203, 0x5203, 0 },
+	{ 0x5330, 0x5330, 0x5330, 0 },
+	{ 0x5460, 0x5460, 0x5460, 0 },
+	{ 0x5592, 0x5592, 0x5592, 0 },
+	{ 0x56c6, 0x56c6, 0x56c6, 0 },
+	{ 0x57fd, 0x57fd, 0x57fd, 0 },
+	{ 0x5937, 0x5937, 0x5937, 0 },
+	{ 0x5a73, 0x5a73, 0x5a73, 0 },
+	{ 0x5bb2, 0x5bb2, 0x5bb2, 0 },
+	{ 0x5cf3, 0x5cf3, 0x5cf3, 0 },
+	{ 0x5e37, 0x5e37, 0x5e37, 0 },
+	{ 0x5f7d, 0x5f7d, 0x5f7d, 0 },
+	{ 0x60c6, 0x60c6, 0x60c6, 0 },
+	{ 0x6212, 0x6212, 0x6212, 0 },
+	{ 0x6360, 0x6360, 0x6360, 0 },
+	{ 0x64b0, 0x64b0, 0x64b0, 0 },
+	{ 0x6604, 0x6604, 0x6604, 0 },
+	{ 0x6759, 0x6759, 0x6759, 0 },
+	{ 0x68b2, 0x68b2, 0x68b2, 0 },
+	{ 0x6a0d, 0x6a0d, 0x6a0d, 0 },
+	{ 0x6b6a, 0x6b6a, 0x6b6a, 0 },
+	{ 0x6ccb, 0x6ccb, 0x6ccb, 0 },
+	{ 0x6e2d, 0x6e2d, 0x6e2d, 0 },
+	{ 0x6f93, 0x6f93, 0x6f93, 0 },
+	{ 0x70fb, 0x70fb, 0x70fb, 0 },
+	{ 0x7266, 0x7266, 0x7266, 0 },
+	{ 0x73d3, 0x73d3, 0x73d3, 0 },
+	{ 0x7543, 0x7543, 0x7543, 0 },
+	{ 0x76b6, 0x76b6, 0x76b6, 0 },
+	{ 0x782b, 0x782b, 0x782b, 0 },
+	{ 0x79a3, 0x79a3, 0x79a3, 0 },
+	{ 0x7b1d, 0x7b1d, 0x7b1d, 0 },
+	{ 0x7c9b, 0x7c9b, 0x7c9b, 0 },
+	{ 0x7e1b, 0x7e1b, 0x7e1b, 0 },
+	{ 0x7f9d, 0x7f9d, 0x7f9d, 0 },
+	{ 0x8123, 0x8123, 0x8123, 0 },
+	{ 0x82ab, 0x82ab, 0x82ab, 0 },
+	{ 0x8436, 0x8436, 0x8436, 0 },
+	{ 0x85c3, 0x85c3, 0x85c3, 0 },
+	{ 0x8753, 0x8753, 0x8753, 0 },
+	{ 0x88e6, 0x88e6, 0x88e6, 0 },
+	{ 0x8a7c, 0x8a7c, 0x8a7c, 0 },
+	{ 0x8c14, 0x8c14, 0x8c14, 0 },
+	{ 0x8daf, 0x8daf, 0x8daf, 0 },
+	{ 0x8f4d, 0x8f4d, 0x8f4d, 0 },
+	{ 0x90ed, 0x90ed, 0x90ed, 0 },
+	{ 0x9290, 0x9290, 0x9290, 0 },
+	{ 0x9436, 0x9436, 0x9436, 0 },
+	{ 0x95df, 0x95df, 0x95df, 0 },
+	{ 0x978b, 0x978b, 0x978b, 0 },
+	{ 0x9939, 0x9939, 0x9939, 0 },
+	{ 0x9aea, 0x9aea, 0x9aea, 0 },
+	{ 0x9c9e, 0x9c9e, 0x9c9e, 0 },
+	{ 0x9e55, 0x9e55, 0x9e55, 0 },
+	{ 0xa00e, 0xa00e, 0xa00e, 0 },
+	{ 0xa1ca, 0xa1ca, 0xa1ca, 0 },
+	{ 0xa389, 0xa389, 0xa389, 0 },
+	{ 0xa54b, 0xa54b, 0xa54b, 0 },
+	{ 0xa710, 0xa710, 0xa710, 0 },
+	{ 0xa8d7, 0xa8d7, 0xa8d7, 0 },
+	{ 0xaaa1, 0xaaa1, 0xaaa1, 0 },
+	{ 0xac6e, 0xac6e, 0xac6e, 0 },
+	{ 0xae3e, 0xae3e, 0xae3e, 0 },
+	{ 0xb011, 0xb011, 0xb011, 0 },
+	{ 0xb1e7, 0xb1e7, 0xb1e7, 0 },
+	{ 0xb3bf, 0xb3bf, 0xb3bf, 0 },
+	{ 0xb59a, 0xb59a, 0xb59a, 0 },
+	{ 0xb778, 0xb778, 0xb778, 0 },
+	{ 0xb959, 0xb959, 0xb959, 0 },
+	{ 0xbb3d, 0xbb3d, 0xbb3d, 0 },
+	{ 0xbd24, 0xbd24, 0xbd24, 0 },
+	{ 0xbf0d, 0xbf0d, 0xbf0d, 0 },
+	{ 0xc0fa, 0xc0fa, 0xc0fa, 0 },
+	{ 0xc2e9, 0xc2e9, 0xc2e9, 0 },
+	{ 0xc4db, 0xc4db, 0xc4db, 0 },
+	{ 0xc6d0, 0xc6d0, 0xc6d0, 0 },
+	{ 0xc8c8, 0xc8c8, 0xc8c8, 0 },
+	{ 0xcac3, 0xcac3, 0xcac3, 0 },
+	{ 0xccc1, 0xccc1, 0xccc1, 0 },
+	{ 0xcec1, 0xcec1, 0xcec1, 0 },
+	{ 0xd0c5, 0xd0c5, 0xd0c5, 0 },
+	{ 0xd2cc, 0xd2cc, 0xd2cc, 0 },
+	{ 0xd4d5, 0xd4d5, 0xd4d5, 0 },
+	{ 0xd6e1, 0xd6e1, 0xd6e1, 0 },
+	{ 0xd8f1, 0xd8f1, 0xd8f1, 0 },
+	{ 0xdb03, 0xdb03, 0xdb03, 0 },
+	{ 0xdd18, 0xdd18, 0xdd18, 0 },
+	{ 0xdf30, 0xdf30, 0xdf30, 0 },
+	{ 0xe14b, 0xe14b, 0xe14b, 0 },
+	{ 0xe369, 0xe369, 0xe369, 0 },
+	{ 0xe58a, 0xe58a, 0xe58a, 0 },
+	{ 0xe7ae, 0xe7ae, 0xe7ae, 0 },
+	{ 0xe9d5, 0xe9d5, 0xe9d5, 0 },
+	{ 0xebff, 0xebff, 0xebff, 0 },
+	{ 0xee2c, 0xee2c, 0xee2c, 0 },
+	{ 0xf05c, 0xf05c, 0xf05c, 0 },
+	{ 0xf28f, 0xf28f, 0xf28f, 0 },
+	{ 0xf4c4, 0xf4c4, 0xf4c4, 0 },
+	{ 0xf6fd, 0xf6fd, 0xf6fd, 0 },
+	{ 0xf939, 0xf939, 0xf939, 0 },
+	{ 0xfb78, 0xfb78, 0xfb78, 0 },
+	{ 0xfdba, 0xfdba, 0xfdba, 0 },
+	{ 0xffff, 0xffff, 0xffff, 0 }
+};
+
+#if 0
+struct vkms_color_lut srgb_eotf = {
+	.base = NULL,
+	. lut_length = LUT_SIZE,
+	.channel_value2index_ratio = drm_int2fixp(0xffff)
+	// .channel_value2index_ratio = 0 //drm_fixp_div(drm_int2fixp(0xffff), drm_int2fixp(LUT_SIZE))
+};
+
+#else
+const struct vkms_color_lut srgb_eotf = {
+	.base = srgb_array,
+	.lut_length = 256,
+	.channel_value2index_ratio = 16711935ll
+};
+
+#endif
+
 static u16 pre_mul_blend_channel(u16 src, u16 dst, u16 alpha)
 {
 	u32 new_color;
@@ -136,6 +414,39 @@  static void apply_lut(const struct vkms_crtc_state *crtc_state, struct line_buff
 	}
 }
 
+static void pre_blend_color_transform(const struct vkms_plane_state *plane_state, struct line_buffer *output_buffer)
+{
+	struct drm_colorop *pipeline = plane_state->base.base.color_pipeline;
+	/* TODO this is probably wrong */
+	struct drm_colorop_state *colorop_state;
+
+	if (!pipeline)
+		return;
+
+	colorop_state = pipeline->state;
+
+	if (!colorop_state)
+		return;
+
+	for (size_t x = 0; x < output_buffer->n_pixels; x++) {
+		struct pixel_argb_u16 *pixel = &output_buffer->pixels[x];
+
+		if (pipeline->type == DRM_COLOROP_1D_CURVE &&
+			colorop_state->bypass == false) {
+			switch (colorop_state->curve_1d_type) {
+				case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
+					break;
+				case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
+				default:
+					pixel->r = apply_lut_to_channel_value(&srgb_eotf, pixel->r, LUT_RED);
+					pixel->g = apply_lut_to_channel_value(&srgb_eotf, pixel->g, LUT_GREEN);
+					pixel->b = apply_lut_to_channel_value(&srgb_eotf, pixel->b, LUT_BLUE);
+					break;
+			}
+		}
+	}
+}
+
 /**
  * @wb_frame_info: The writeback frame buffer metadata
  * @crtc_state: The crtc state
@@ -168,8 +479,13 @@  static void blend(struct vkms_writeback_job *wb,
 				continue;
 
 			plane[i]->plane_read(stage_buffer, plane[i]->frame_info, y);
+
+			/* do per-plane color transformations here */
+			// pre_blend_color_transform(plane[i], stage_buffer);
+
 			pre_mul_alpha_blend(plane[i]->frame_info, stage_buffer,
 					    output_buffer);
+			pre_blend_color_transform(plane[i], output_buffer);
 		}
 
 		apply_lut(crtc_state, output_buffer);
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index 310b31f47928..c04f714cd486 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -168,4 +168,8 @@  void vkms_set_composer(struct vkms_output *out, bool enabled);
 /* Writeback */
 int vkms_enable_writeback_connector(struct vkms_device *vkmsdev);
 
+/* Colorops */
+int vkms_initialize_colorops(struct drm_plane *plane);
+
+
 #endif /* _VKMS_DRV_H_ */
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index b3f8a115cc23..cbffbdd7cbf9 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -237,5 +237,7 @@  struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
 
 	drm_plane_helper_add(&plane->base, funcs);
 
+	vkms_initialize_colorops(&plane->base);
+
 	return plane;
 }