From c7245fe46212ae9f2337c30da6c66d4dfef97dcd Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 12 Jul 2017 18:51:02 +0300 Subject: [PATCH] drm/atomic: Make private objs proper objects Make the atomic private object stuff less special by introducing proper base classes for the object and its state. Drivers can embed these in their own appropriate objects, after which these things will work exactly like the plane/crtc/connector states during atomic operations. v2: Reorder to not depend on drm_dynarray (Daniel) Change-Id: I475f3c46440934b8d6f461935b6413624b7d34c7 Cc: Dhinakaran Pandiyan Cc: Daniel Vetter Reviewed-by: Daniel Vetter #v1 Signed-off-by: Ville Syrj?l? Link: http://patchwork.freedesktop.org/patch/msgid/20170712155102.26276-3-ville.syrjala@linux.intel.com Signed-off-by: Ao Xu --- drivers/gpu/drm/drm_atomic.c | 77 +++++++++++++++++++++++++--------- drivers/gpu/drm/drm_atomic_helper.c | 26 ++++++++++-- include/drm/drm_atomic.h | 84 ++++++++++++++++--------------------- include/drm/drm_atomic_helper.h | 4 ++ 4 files changed, 118 insertions(+), 73 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index af6b397..b3f8543 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -189,12 +189,15 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) } for (i = 0; i < state->num_private_objs; i++) { - void *obj_state = state->private_objs[i].obj_state; + struct drm_private_obj *obj = state->private_objs[i].ptr; - state->private_objs[i].funcs->destroy_state(obj_state); - state->private_objs[i].obj = NULL; - state->private_objs[i].obj_state = NULL; - state->private_objs[i].funcs = NULL; + if (!obj) + continue; + + obj->funcs->atomic_destroy_state(obj, + state->private_objs[i].state); + state->private_objs[i].ptr = NULL; + state->private_objs[i].state = NULL; } state->num_private_objs = 0; @@ -939,11 +942,44 @@ static int drm_atomic_plane_check(struct drm_plane *plane, } /** + * drm_atomic_private_obj_init - initialize private object + * @obj: private object + * @state: initial private object state + * @funcs: pointer to the struct of function pointers that identify the object + * type + * + * Initialize the private object, which can be embedded into any + * driver private object that needs its own atomic state. + */ +void +drm_atomic_private_obj_init(struct drm_private_obj *obj, + struct drm_private_state *state, + const struct drm_private_state_funcs *funcs) +{ + memset(obj, 0, sizeof(*obj)); + + obj->state = state; + obj->funcs = funcs; +} +EXPORT_SYMBOL(drm_atomic_private_obj_init); + +/** + * drm_atomic_private_obj_fini - finalize private object + * @obj: private object + * + * Finalize the private object. + */ +void +drm_atomic_private_obj_fini(struct drm_private_obj *obj) +{ + obj->funcs->atomic_destroy_state(obj, obj->state); +} +EXPORT_SYMBOL(drm_atomic_private_obj_fini); + +/** * drm_atomic_get_private_obj_state - get private object state * @state: global atomic state * @obj: private object to get the state for - * @funcs: pointer to the struct of function pointers that identify the object - * type * * This function returns the private object state for the given private object, * allocating the state if needed. It does not grab any locks as the caller is @@ -953,18 +989,18 @@ static int drm_atomic_plane_check(struct drm_plane *plane, * * Either the allocated state or the error code encoded into a pointer. */ -void * -drm_atomic_get_private_obj_state(struct drm_atomic_state *state, void *obj, - const struct drm_private_state_funcs *funcs) +struct drm_private_state * +drm_atomic_get_private_obj_state(struct drm_atomic_state *state, + struct drm_private_obj *obj) { int index, num_objs, i; size_t size; struct __drm_private_objs_state *arr; + struct drm_private_state *obj_state; for (i = 0; i < state->num_private_objs; i++) - if (obj == state->private_objs[i].obj && - state->private_objs[i].obj_state) - return state->private_objs[i].obj_state; + if (obj == state->private_objs[i].ptr) + return state->private_objs[i].state; num_objs = state->num_private_objs + 1; size = sizeof(*state->private_objs) * num_objs; @@ -976,18 +1012,19 @@ drm_atomic_get_private_obj_state(struct drm_atomic_state *state, void *obj, index = state->num_private_objs; memset(&state->private_objs[index], 0, sizeof(*state->private_objs)); - state->private_objs[index].obj_state = funcs->duplicate_state(state, obj); - if (!state->private_objs[index].obj_state) + obj_state = obj->funcs->atomic_duplicate_state(obj); + if (!obj_state) return ERR_PTR(-ENOMEM); - state->private_objs[index].obj = obj; - state->private_objs[index].funcs = funcs; + state->private_objs[index].state = obj_state; + state->private_objs[index].ptr = obj; + state->num_private_objs = num_objs; - DRM_DEBUG_ATOMIC("Added new private object state %p to %p\n", - state->private_objs[index].obj_state, state); + DRM_DEBUG_ATOMIC("Added new private object %p state %p to %p\n", + obj, obj_state, state); - return state->private_objs[index].obj_state; + return obj_state; } EXPORT_SYMBOL(drm_atomic_get_private_obj_state); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4139d04..f510925 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2011,8 +2011,8 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, struct drm_plane *plane; struct drm_plane_state *plane_state; struct drm_crtc_commit *commit; - void *obj, *obj_state; - const struct drm_private_state_funcs *funcs; + struct drm_private_obj *obj; + struct drm_private_state *obj_state; if (stall) { for_each_crtc_in_state(state, crtc, crtc_state, i) { @@ -2062,8 +2062,11 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, plane->state->state = NULL; } - __for_each_private_obj(state, obj, obj_state, i, funcs) - funcs->swap_state(obj, &state->private_objs[i].obj_state); + for_each_private_obj(state, obj, obj_state, i) { + obj->state->state = state; + swap(state->private_objs[i].state, obj->state); + obj->state->state = NULL; + } } EXPORT_SYMBOL(drm_atomic_helper_swap_state); @@ -3490,3 +3493,18 @@ backoff: goto retry; } EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set); + +/** + * __drm_atomic_helper_private_duplicate_state - copy atomic private state + * @obj: CRTC object + * @state: new private object state + * + * Copies atomic state from a private objects's current state and resets inferred values. + * This is useful for drivers that subclass the private state. + */ +void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + memcpy(state, obj->state, sizeof(*state)); +} +EXPORT_SYMBOL(__drm_atomic_helper_private_obj_duplicate_state); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 7c9e831..a27eecee 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -152,6 +152,9 @@ struct __drm_connnectors_state { struct drm_connector_state *state; }; +struct drm_private_obj; +struct drm_private_state; + /** * struct drm_private_state_funcs - atomic state functions for private objects * @@ -164,7 +167,7 @@ struct __drm_connnectors_state { */ struct drm_private_state_funcs { /** - * @duplicate_state: + * @atomic_duplicate_state: * * Duplicate the current state of the private object and return it. It * is an error to call this before obj->state has been initialized. @@ -174,29 +177,30 @@ struct drm_private_state_funcs { * Duplicated atomic state or NULL when obj->state is not * initialized or allocation failed. */ - void *(*duplicate_state)(struct drm_atomic_state *state, void *obj); + struct drm_private_state *(*atomic_duplicate_state)(struct drm_private_obj *obj); /** - * @swap_state: + * @atomic_destroy_state: * - * This function swaps the existing state of a private object @obj with - * it's newly created state, the pointer to which is passed as - * @obj_state_ptr. + * Frees the private object state created with @atomic_duplicate_state. */ - void (*swap_state)(void *obj, void **obj_state_ptr); + void (*atomic_destroy_state)(struct drm_private_obj *obj, + struct drm_private_state *state); +}; - /** - * @destroy_state: - * - * Frees the private object state created with @duplicate_state. - */ - void (*destroy_state)(void *obj_state); +struct drm_private_obj { + struct drm_private_state *state; + + const struct drm_private_state_funcs *funcs; +}; + +struct drm_private_state { + struct drm_atomic_state *state; }; struct __drm_private_objs_state { - void *obj; - void *obj_state; - const struct drm_private_state_funcs *funcs; + struct drm_private_obj *ptr; + struct drm_private_state *state; }; /** @@ -271,10 +275,14 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, struct drm_connector_state *state, struct drm_property *property, uint64_t val); -void * __must_check +void drm_atomic_private_obj_init(struct drm_private_obj *obj, + struct drm_private_state *state, + const struct drm_private_state_funcs *funcs); +void drm_atomic_private_obj_fini(struct drm_private_obj *obj); + +struct drm_private_state * __must_check drm_atomic_get_private_obj_state(struct drm_atomic_state *state, - void *obj, - const struct drm_private_state_funcs *funcs); + struct drm_private_obj *obj); /** * drm_atomic_get_existing_crtc_state - get crtc state, if it exists @@ -419,43 +427,21 @@ int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state); for_each_if (plane_state) /** - * __for_each_private_obj - iterate over all private objects - * @__state: &struct drm_atomic_state pointer - * @obj: private object iteration cursor - * @obj_state: private object state iteration cursor - * @__i: int iteration cursor, for macro-internal use - * @__funcs: &struct drm_private_state_funcs iteration cursor - * - * This macro iterates over the array containing private object data in atomic - * state - */ -#define __for_each_private_obj(__state, obj, obj_state, __i, __funcs) \ - for ((__i) = 0; \ - (__i) < (__state)->num_private_objs && \ - ((obj) = (__state)->private_objs[__i].obj, \ - (__funcs) = (__state)->private_objs[__i].funcs, \ - (obj_state) = (__state)->private_objs[__i].obj_state, \ - 1); \ - (__i)++) \ - -/** * for_each_private_obj - iterate over a specify type of private object * @__state: &struct drm_atomic_state pointer - * @obj_funcs: &struct drm_private_state_funcs function table to filter - * private objects * @obj: private object iteration cursor * @obj_state: private object state iteration cursor * @__i: int iteration cursor, for macro-internal use - * @__funcs: &struct drm_private_state_funcs iteration cursor * - * This macro iterates over the private objects state array while filtering the - * objects based on the vfunc table that is passed as @obj_funcs. New macros - * can be created by passing in the vfunc table associated with a specific - * private object. + * This macro iterates over all private objects in an atomic update. */ -#define for_each_private_obj(__state, obj_funcs, obj, obj_state, __i, __funcs) \ - __for_each_private_obj(__state, obj, obj_state, __i, __funcs) \ - for_each_if (__funcs == obj_funcs) +#define for_each_private_obj(__state, obj, obj_state, __i) \ + for ((__i) = 0; \ + (__i) < (__state)->num_private_objs && \ + ((obj) = (__state)->private_objs[__i].ptr, \ + (obj_state) = (__state)->private_objs[__i].state, 1); \ + (__i)++) \ + for_each_if (obj) /** * drm_atomic_crtc_needs_modeset - compute combined modeset need diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 7ff92b0..34c00d5 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -33,6 +33,8 @@ #include struct drm_atomic_state; +struct drm_private_obj; +struct drm_private_state; int drm_atomic_helper_check_modeset(struct drm_device *dev, struct drm_atomic_state *state); @@ -166,6 +168,8 @@ void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size); +void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj, + struct drm_private_state *state); /** * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC -- 2.7.4