diff mbox series

[v8,4/4] NOTFORMERGE: drm/logicvc: Add plane colorkey support

Message ID 20201223212947.160565-5-paul.kocialkowski@bootlin.com
State Superseded
Headers show
Series drm: LogiCVC display controller support | expand

Commit Message

Paul Kocialkowski Dec. 23, 2020, 9:29 p.m. UTC
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 drivers/gpu/drm/logicvc/logicvc_drm.h   |   3 +
 drivers/gpu/drm/logicvc/logicvc_layer.c | 150 +++++++++++++++++++++++-
 drivers/gpu/drm/logicvc/logicvc_layer.h |   7 ++
 3 files changed, 154 insertions(+), 6 deletions(-)

Comments

Simon Ser Dec. 23, 2020, 10:20 p.m. UTC | #1
nouveau already has something for colorkey:
https://drmdb.emersion.fr/properties/4008636142/colorkey

I know this is marked "not for merge", but it would be nice to discuss
with them and come up with a standardized property.
Ilia Mirkin Dec. 23, 2020, 11:31 p.m. UTC | #2
FWIW this is something I added, hoping it was going to get used at
some point, but I never followed up with support in xf86-video-nouveau
for Xv. At this point, I'm not sure I ever will. I encoded the
"enabled" part into the value with a high bit (1<<24) -- not sure that
was such a great idea. All NVIDIA hardware supports colorkey (and not
actual alpha, until the very latest GPUs - Volta/Turing families),
although my implementation only covers the pre-G80 series (i.e. DX9
and earlier GPUs - pre-2008). Should a determination of usefulness be
reached, it would be easy to implement on the remainder though.

Cheers,

  -ilia

On Wed, Dec 23, 2020 at 5:20 PM Simon Ser <contact@emersion.fr> wrote:
>
> nouveau already has something for colorkey:
> https://drmdb.emersion.fr/properties/4008636142/colorkey
>
> I know this is marked "not for merge", but it would be nice to discuss
> with them and come up with a standardized property.
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
Paul Kocialkowski Jan. 5, 2021, 3 p.m. UTC | #3
Hi,

On Wed 23 Dec 20, 18:31, Ilia Mirkin wrote:
> FWIW this is something I added, hoping it was going to get used at
> some point, but I never followed up with support in xf86-video-nouveau
> for Xv. At this point, I'm not sure I ever will. I encoded the
> "enabled" part into the value with a high bit (1<<24) -- not sure that
> was such a great idea. All NVIDIA hardware supports colorkey (and not
> actual alpha, until the very latest GPUs - Volta/Turing families),
> although my implementation only covers the pre-G80 series (i.e. DX9
> and earlier GPUs - pre-2008). Should a determination of usefulness be
> reached, it would be easy to implement on the remainder though.

Interesting to know!

Regarding a generic colorkey property, there was a discussion under thread:
drm: Add generic colorkey properties for display planes

and the latest proposal (RFC v4) can be found here:
https://patchwork.ozlabs.org/project/linux-tegra/patch/20180807172202.1961-2-digetx@gmail.com/

It looks like this was much more complex than anticipated and the series
was more or less abandonned. I didn't feel like picking it up in my logicvc
series so I kept the colorkey patch as not for merge.

If someone's up for picking the proposal and continuing the discussion,
I could provide insight on how it would fit with logicvc though!

Cheers,

Paul

> On Wed, Dec 23, 2020 at 5:20 PM Simon Ser <contact@emersion.fr> wrote:
> >
> > nouveau already has something for colorkey:
> > https://drmdb.emersion.fr/properties/4008636142/colorkey
> >
> > I know this is marked "not for merge", but it would be nice to discuss
> > with them and come up with a standardized property.
diff mbox series

Patch

diff --git a/drivers/gpu/drm/logicvc/logicvc_drm.h b/drivers/gpu/drm/logicvc/logicvc_drm.h
index 68bbac6c4ab9..d69a686ab0f1 100644
--- a/drivers/gpu/drm/logicvc/logicvc_drm.h
+++ b/drivers/gpu/drm/logicvc/logicvc_drm.h
@@ -59,6 +59,9 @@  struct logicvc_drm {
 	struct list_head layers_list;
 	struct logicvc_crtc *crtc;
 	struct logicvc_interface *interface;
+
+	struct drm_property *colorkey_enabled_property;
+	struct drm_property *colorkey_value_property;
 };
 
 #endif
diff --git a/drivers/gpu/drm/logicvc/logicvc_layer.c b/drivers/gpu/drm/logicvc/logicvc_layer.c
index 313043d29128..e2c3140926f1 100644
--- a/drivers/gpu/drm/logicvc/logicvc_layer.c
+++ b/drivers/gpu/drm/logicvc/logicvc_layer.c
@@ -23,6 +23,8 @@ 
 
 #define logicvc_layer(p) \
 	container_of(p, struct logicvc_layer, drm_plane)
+#define logicvc_layer_state(p) \
+	container_of(p, struct logicvc_layer_state, drm_plane_state)
 
 static uint32_t logicvc_layer_formats_rgb16[] = {
 	DRM_FORMAT_RGB565,
@@ -138,6 +140,7 @@  static void logicvc_plane_atomic_update(struct drm_plane *drm_plane,
 	struct logicvc_drm *logicvc = logicvc_drm(drm_plane->dev);
 	struct drm_device *drm_dev = &logicvc->drm_dev;
 	struct drm_plane_state *state = drm_plane->state;
+	struct logicvc_layer_state *layer_state = logicvc_layer_state(state);
 	struct drm_crtc *drm_crtc = &logicvc->crtc->drm_crtc;
 	struct drm_display_mode *mode = &drm_crtc->state->adjusted_mode;
 	struct drm_framebuffer *fb = state->fb;
@@ -214,6 +217,15 @@  static void logicvc_plane_atomic_update(struct drm_plane *drm_plane,
 			     alpha);
 	}
 
+	/* Layer colorkey */
+
+	if (layer_state->colorkey_enabled) {
+		reg = layer_state->colorkey_value;
+
+		regmap_write(logicvc->regmap,
+			     LOGICVC_LAYER_COLOR_KEY_REG(index), reg);
+	}
+
 	/* Layer control */
 
 	reg = LOGICVC_LAYER_CTRL_ENABLE;
@@ -221,7 +233,8 @@  static void logicvc_plane_atomic_update(struct drm_plane *drm_plane,
 	if (logicvc_layer_format_inverted(fb->format->format))
 		reg |= LOGICVC_LAYER_CTRL_PIXEL_FORMAT_INVERT;
 
-	reg |= LOGICVC_LAYER_CTRL_COLOR_KEY_DISABLE;
+	if (!layer_state->colorkey_enabled)
+		reg |= LOGICVC_LAYER_CTRL_COLOR_KEY_DISABLE;
 
 	regmap_write(logicvc->regmap, LOGICVC_LAYER_CTRL_REG(index), reg);
 }
@@ -242,13 +255,109 @@  static struct drm_plane_helper_funcs logicvc_plane_helper_funcs = {
 	.atomic_disable		= logicvc_plane_atomic_disable,
 };
 
+static void logicvc_plane_reset(struct drm_plane *drm_plane)
+{
+	struct logicvc_drm *logicvc = logicvc_drm(drm_plane->dev);
+	struct device *dev = logicvc->drm_dev.dev;
+	struct logicvc_layer_state *layer_state;
+
+	if (drm_plane->state) {
+		layer_state = logicvc_layer_state(drm_plane->state);
+		__drm_atomic_helper_plane_destroy_state(drm_plane->state);
+		devm_kfree(dev, layer_state);
+		drm_plane->state = NULL;
+	}
+
+	layer_state = devm_kzalloc(dev, sizeof(*layer_state), GFP_KERNEL);
+	if (!layer_state)
+		return;
+
+	__drm_atomic_helper_plane_reset(drm_plane,
+					&layer_state->drm_plane_state);
+}
+
+static struct drm_plane_state *
+logicvc_plane_atomic_duplicate_state(struct drm_plane *drm_plane)
+{
+	struct logicvc_drm *logicvc = logicvc_drm(drm_plane->dev);
+	struct device *dev = logicvc->drm_dev.dev;
+	struct logicvc_layer_state *layer_state_current;
+	struct logicvc_layer_state *layer_state;
+
+	if (WARN_ON(!drm_plane->state))
+		return NULL;
+
+	layer_state_current = logicvc_layer_state(drm_plane->state);
+	layer_state = devm_kzalloc(dev, sizeof(*layer_state), GFP_KERNEL);
+	if (!layer_state)
+		return NULL;
+
+	layer_state->colorkey_enabled = layer_state_current->colorkey_enabled;
+	layer_state->colorkey_value = layer_state_current->colorkey_value;
+
+	__drm_atomic_helper_plane_duplicate_state(drm_plane,
+						  &layer_state->drm_plane_state);
+
+	return &layer_state->drm_plane_state;
+}
+
+static void logicvc_plane_destroy_state(struct drm_plane *drm_plane,
+					struct drm_plane_state *state)
+{
+	struct logicvc_drm *logicvc = logicvc_drm(drm_plane->dev);
+	struct device *dev = logicvc->drm_dev.dev;
+	struct logicvc_layer_state *layer_state = logicvc_layer_state(state);
+
+	__drm_atomic_helper_plane_destroy_state(&layer_state->drm_plane_state);
+
+	devm_kfree(dev, layer_state);
+}
+
+static int logicvc_plane_atomic_set_property(struct drm_plane *drm_plane,
+					     struct drm_plane_state *state,
+					     struct drm_property *property,
+					     uint64_t value)
+{
+	struct logicvc_drm *logicvc = logicvc_drm(drm_plane->dev);
+	struct logicvc_layer_state *layer_state = logicvc_layer_state(state);
+
+	if (property == logicvc->colorkey_enabled_property)
+		layer_state->colorkey_enabled = !!value;
+	else if (property == logicvc->colorkey_value_property)
+		layer_state->colorkey_value = (uint32_t)value;
+	else
+		return -ENOENT;
+
+	return 0;
+}
+
+static int logicvc_plane_atomic_get_property(struct drm_plane *drm_plane,
+					     const struct drm_plane_state *state,
+					     struct drm_property *property,
+					     uint64_t *value)
+{
+	struct logicvc_drm *logicvc = logicvc_drm(drm_plane->dev);
+	struct logicvc_layer_state *layer_state = logicvc_layer_state(state);
+
+	if (property == logicvc->colorkey_enabled_property)
+		*value = layer_state->colorkey_enabled;
+	else if (property == logicvc->colorkey_value_property)
+		*value = layer_state->colorkey_value;
+	else
+		return -ENOENT;
+
+	return 0;
+}
+
 static const struct drm_plane_funcs logicvc_plane_funcs = {
 	.update_plane		= drm_atomic_helper_update_plane,
 	.disable_plane		= drm_atomic_helper_disable_plane,
 	.destroy		= drm_plane_cleanup,
-	.reset			= drm_atomic_helper_plane_reset,
-	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
-	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+	.reset			= logicvc_plane_reset,
+	.atomic_duplicate_state	= logicvc_plane_atomic_duplicate_state,
+	.atomic_destroy_state	= logicvc_plane_destroy_state,
+	.atomic_set_property	= logicvc_plane_atomic_set_property,
+	.atomic_get_property	= logicvc_plane_atomic_get_property,
 };
 
 int logicvc_layer_buffer_find_setup(struct logicvc_drm *logicvc,
@@ -345,7 +454,8 @@  int logicvc_layer_buffer_find_setup(struct logicvc_drm *logicvc,
 	return 0;
 }
 
-static struct logicvc_layer_formats *logicvc_layer_formats_lookup(struct logicvc_layer *layer)
+static struct logicvc_layer_formats *
+logicvc_layer_formats_lookup(struct logicvc_layer *layer)
 {
 	bool alpha;
 	unsigned int i = 0;
@@ -364,7 +474,8 @@  static struct logicvc_layer_formats *logicvc_layer_formats_lookup(struct logicvc
 	return NULL;
 }
 
-static unsigned int logicvc_layer_formats_count(struct logicvc_layer_formats *formats)
+static unsigned int
+logicvc_layer_formats_count(struct logicvc_layer_formats *formats)
 {
 	unsigned int count = 0;
 
@@ -533,6 +644,11 @@  static int logicvc_layer_init(struct logicvc_drm *logicvc,
 
 	drm_plane_create_zpos_immutable_property(&layer->drm_plane, zpos);
 
+	drm_object_attach_property(&layer->drm_plane.base,
+				   logicvc->colorkey_enabled_property, 0);
+	drm_object_attach_property(&layer->drm_plane.base,
+				   logicvc->colorkey_value_property, 0);
+
 	drm_dbg_kms(drm_dev, "Registering layer #%d\n", index);
 
 	layer->formats = formats;
@@ -581,6 +697,17 @@  int logicvc_layers_init(struct logicvc_drm *logicvc)
 	struct logicvc_layer *next;
 	int ret = 0;
 
+	logicvc->colorkey_enabled_property =
+		drm_property_create_bool(drm_dev, 0, "colorkey_enabled");
+	if (!logicvc->colorkey_enabled_property)
+		goto error;
+
+	logicvc->colorkey_value_property =
+		drm_property_create_range(drm_dev, 0, "colorkey_value",
+					  0, 0xffffffff);
+	if (!logicvc->colorkey_value_property)
+		goto error;
+
 	layers_node = of_get_child_by_name(of_node, "layers");
 	if (!layers_node) {
 		drm_err(drm_dev, "No layers node found in the description\n");
@@ -620,5 +747,16 @@  int logicvc_layers_init(struct logicvc_drm *logicvc)
 	list_for_each_entry_safe(layer, next, &logicvc->layers_list, list)
 		logicvc_layer_fini(logicvc, layer);
 
+	if (logicvc->colorkey_value_property) {
+		drm_property_destroy(drm_dev, logicvc->colorkey_value_property);
+		logicvc->colorkey_value_property = NULL;
+	}
+
+	if (logicvc->colorkey_enabled_property) {
+		drm_property_destroy(drm_dev,
+				     logicvc->colorkey_enabled_property);
+		logicvc->colorkey_enabled_property = NULL;
+	}
+
 	return ret;
 }
diff --git a/drivers/gpu/drm/logicvc/logicvc_layer.h b/drivers/gpu/drm/logicvc/logicvc_layer.h
index c5767c81f446..69bb208ad79c 100644
--- a/drivers/gpu/drm/logicvc/logicvc_layer.h
+++ b/drivers/gpu/drm/logicvc/logicvc_layer.h
@@ -39,6 +39,13 @@  struct logicvc_layer_formats {
 	uint32_t *formats;
 };
 
+struct logicvc_layer_state {
+	struct drm_plane_state drm_plane_state;
+
+	bool colorkey_enabled;
+	uint32_t colorkey_value;
+};
+
 struct logicvc_layer {
 	struct logicvc_layer_config config;
 	struct logicvc_layer_formats *formats;