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
