The DRM_MODE_ATOMIC_RESET flag allows userspace to reset all object
states to their defaults before applying new property values. Testing
that this mechanism works correctly requires a property that the test
can set to a non-default value and then verify is properly reset.

Using a standard property for this is problematic: compositors like
Mutter enumerate and track all known properties, making it difficult
to isolate the reset behavior from the compositor's own property
management.

Add a "vkms-test-do-not-use-in-prod" range property to vkms planes.
The property is stored in vkms_plane_state, duplicated across state
copies, and initialized from its registered default in
atomic_create_state via drm_object_property_get_default_value().

Signed-off-by: Maxime Ripard <[email protected]>
---
 drivers/gpu/drm/vkms/vkms_drv.h   |  3 ++
 drivers/gpu/drm/vkms/vkms_plane.c | 61 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index dea6cad3f1b9..384616095b45 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -144,20 +144,23 @@ struct conversion_matrix {
  * @base: base plane state
  * @frame_info: data required for composing computation
  * @pixel_read_line: function to read a pixel line in this plane. The creator 
of a
  *                  struct vkms_plane_state must ensure that this pointer is 
valid
  * @conversion_matrix: matrix used for yuv formats to convert to rgb
+ * @vkms_test_do_not_use_value: driver-specific property for testing only
  */
 struct vkms_plane_state {
        struct drm_shadow_plane_state base;
        struct vkms_frame_info frame_info;
        pixel_read_line_t pixel_read_line;
        struct conversion_matrix conversion_matrix;
+       unsigned int vkms_test_do_not_use_value;
 };
 
 struct vkms_plane {
        struct drm_plane base;
+       struct drm_property *vkms_test_do_not_use_property;
 };
 
 struct vkms_color_lut {
        struct drm_color_lut *base;
        size_t lut_length;
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c 
b/drivers/gpu/drm/vkms/vkms_plane.c
index fd3d34dcf0fe..0ebc131c2788 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -9,14 +9,18 @@
 #include <drm/drm_colorop.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_print.h>
+#include <drm/drm_property.h>
 
 #include "vkms_drv.h"
 #include "vkms_formats.h"
 
+#define to_vkms_plane(target) \
+       container_of_const(target, struct vkms_plane, base)
+
 static const u32 vkms_formats[] = {
        DRM_FORMAT_ARGB8888,
        DRM_FORMAT_ABGR8888,
        DRM_FORMAT_BGRA8888,
        DRM_FORMAT_RGBA8888,
@@ -52,16 +56,19 @@ static const u32 vkms_formats[] = {
 };
 
 static struct drm_plane_state *
 vkms_plane_duplicate_state(struct drm_plane *plane)
 {
+       struct vkms_plane_state *old_state = to_vkms_plane_state(plane->state);
        struct vkms_plane_state *vkms_state;
 
        vkms_state = kzalloc_obj(*vkms_state);
        if (!vkms_state)
                return NULL;
 
+       vkms_state->vkms_test_do_not_use_value = 
old_state->vkms_test_do_not_use_value;
+
        __drm_gem_duplicate_shadow_plane_state(plane, &vkms_state->base);
 
        return &vkms_state->base.base;
 }
 
@@ -83,28 +90,69 @@ static void vkms_plane_destroy_state(struct drm_plane 
*plane,
        kfree(vkms_state);
 }
 
 static struct drm_plane_state *vkms_plane_create_state(struct drm_plane *plane)
 {
+       struct vkms_plane *vkms_plane = to_vkms_plane(plane);
        struct vkms_plane_state *vkms_state;
+       u64 val;
 
        vkms_state = kzalloc_obj(*vkms_state);
        if (!vkms_state) {
                DRM_ERROR("Cannot allocate vkms_plane_state\n");
                return ERR_PTR(-ENOMEM);
        }
 
        __drm_gem_shadow_plane_state_init(plane, &vkms_state->base);
 
+       if (!drm_object_property_get_default_value(&plane->base,
+                                                  
vkms_plane->vkms_test_do_not_use_property,
+                                                  &val))
+               vkms_state->vkms_test_do_not_use_value = val;
+
        return &(&vkms_state->base)->base;
 }
 
+static int vkms_plane_atomic_set_property(struct drm_plane *plane,
+                                         struct drm_plane_state *state,
+                                         struct drm_property *property,
+                                         uint64_t val)
+{
+       struct vkms_plane *vkms_plane = to_vkms_plane(plane);
+       struct vkms_plane_state *vkms_state = to_vkms_plane_state(state);
+
+       if (property == vkms_plane->vkms_test_do_not_use_property) {
+               vkms_state->vkms_test_do_not_use_value = val;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int vkms_plane_atomic_get_property(struct drm_plane *plane,
+                                         const struct drm_plane_state *state,
+                                         struct drm_property *property,
+                                         uint64_t *val)
+{
+       const struct vkms_plane_state *vkms_state = to_vkms_plane_state(state);
+       const struct vkms_plane *vkms_plane = to_vkms_plane(plane);
+
+       if (property == vkms_plane->vkms_test_do_not_use_property) {
+               *val = vkms_state->vkms_test_do_not_use_value;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
 static const struct drm_plane_funcs vkms_plane_funcs = {
        .update_plane           = drm_atomic_helper_update_plane,
        .disable_plane          = drm_atomic_helper_disable_plane,
-       .atomic_create_state = vkms_plane_create_state,
-       .atomic_duplicate_state = vkms_plane_duplicate_state,
+       .atomic_set_property    = vkms_plane_atomic_set_property,
+       .atomic_get_property    = vkms_plane_atomic_get_property,
+       .atomic_create_state    = vkms_plane_create_state,
+       .atomic_duplicate_state = vkms_plane_duplicate_state,
        .atomic_destroy_state   = vkms_plane_destroy_state,
 };
 
 static void vkms_plane_atomic_update(struct drm_plane *plane,
                                     struct drm_atomic_commit *state)
@@ -281,10 +329,19 @@ struct vkms_plane *vkms_plane_init(struct vkms_device 
*vkmsdev,
                                          BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
                                          BIT(DRM_COLOR_YCBCR_FULL_RANGE),
                                          DRM_COLOR_YCBCR_BT601,
                                          DRM_COLOR_YCBCR_FULL_RANGE);
 
+       plane->vkms_test_do_not_use_property =
+               drm_property_create_range(dev, 0,
+                                         "vkms-test-do-not-use-in-prod",
+                                         0, U32_MAX);
+       if (plane->vkms_test_do_not_use_property)
+               drm_object_attach_property(&plane->base.base,
+                                          plane->vkms_test_do_not_use_property,
+                                          0);
+
        if (vkms_config_plane_get_default_pipeline(plane_cfg))
                vkms_initialize_colorops(&plane->base);
 
        return plane;
 }

-- 
2.55.0

Reply via email to