mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
drm/atomic-helper: Add {begin,end}_fb_access to plane helpers
Add {begin,end}_fb_access helpers to run at the beginning and end of an atomic commit. The begin_fb_access helper acquires resources that are necessary to perform the atomic commit. It it similar to prepare_fb, except that the resources are to be released at the end of the commit. Resources acquired by prepare_fb are held until after the next pageflip. The end_fb_access helper performs the corresponding resource cleanup. Atomic helpers call it with the new plane state. This is different from cleanup_fb, which releases resources of the old plane state. v2: * fix typos in commit message (Javier) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20221025101737.8874-2-tzimmermann@suse.de
This commit is contained in:
parent
260cd59a54
commit
94d879eaf7
5 changed files with 126 additions and 14 deletions
|
@ -2536,7 +2536,7 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
|
||||||
if (funcs->prepare_fb) {
|
if (funcs->prepare_fb) {
|
||||||
ret = funcs->prepare_fb(plane, new_plane_state);
|
ret = funcs->prepare_fb(plane, new_plane_state);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail_prepare_fb;
|
||||||
} else {
|
} else {
|
||||||
WARN_ON_ONCE(funcs->cleanup_fb);
|
WARN_ON_ONCE(funcs->cleanup_fb);
|
||||||
|
|
||||||
|
@ -2545,13 +2545,34 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
|
||||||
|
|
||||||
ret = drm_gem_plane_helper_prepare_fb(plane, new_plane_state);
|
ret = drm_gem_plane_helper_prepare_fb(plane, new_plane_state);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail_prepare_fb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
|
||||||
|
const struct drm_plane_helper_funcs *funcs = plane->helper_private;
|
||||||
|
|
||||||
|
if (funcs->begin_fb_access) {
|
||||||
|
ret = funcs->begin_fb_access(plane, new_plane_state);
|
||||||
|
if (ret)
|
||||||
|
goto fail_begin_fb_access;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail_begin_fb_access:
|
||||||
|
for_each_new_plane_in_state(state, plane, new_plane_state, j) {
|
||||||
|
const struct drm_plane_helper_funcs *funcs = plane->helper_private;
|
||||||
|
|
||||||
|
if (j >= i)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (funcs->end_fb_access)
|
||||||
|
funcs->end_fb_access(plane, new_plane_state);
|
||||||
|
}
|
||||||
|
i = j; /* set i to upper limit to cleanup all planes */
|
||||||
|
fail_prepare_fb:
|
||||||
for_each_new_plane_in_state(state, plane, new_plane_state, j) {
|
for_each_new_plane_in_state(state, plane, new_plane_state, j) {
|
||||||
const struct drm_plane_helper_funcs *funcs;
|
const struct drm_plane_helper_funcs *funcs;
|
||||||
|
|
||||||
|
@ -2827,6 +2848,13 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
|
||||||
struct drm_plane_state *old_plane_state, *new_plane_state;
|
struct drm_plane_state *old_plane_state, *new_plane_state;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
|
||||||
|
const struct drm_plane_helper_funcs *funcs = plane->helper_private;
|
||||||
|
|
||||||
|
if (funcs->end_fb_access)
|
||||||
|
funcs->end_fb_access(plane, new_plane_state);
|
||||||
|
}
|
||||||
|
|
||||||
for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
|
for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
|
||||||
const struct drm_plane_helper_funcs *funcs;
|
const struct drm_plane_helper_funcs *funcs;
|
||||||
struct drm_plane_state *plane_state;
|
struct drm_plane_state *plane_state;
|
||||||
|
|
|
@ -414,16 +414,14 @@ void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *
|
||||||
EXPORT_SYMBOL(drm_gem_cleanup_shadow_fb);
|
EXPORT_SYMBOL(drm_gem_cleanup_shadow_fb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_gem_simple_kms_prepare_shadow_fb - prepares shadow framebuffers
|
* drm_gem_simple_kms_begin_shadow_fb_access - prepares shadow framebuffers for CPU access
|
||||||
* @pipe: the simple display pipe
|
* @pipe: the simple display pipe
|
||||||
* @plane_state: the plane state of type struct drm_shadow_plane_state
|
* @plane_state: the plane state of type struct drm_shadow_plane_state
|
||||||
*
|
*
|
||||||
* This function implements struct drm_simple_display_funcs.prepare_fb. It
|
* This function implements struct drm_simple_display_funcs.begin_fb_access.
|
||||||
* maps all buffer objects of the plane's framebuffer into kernel address
|
|
||||||
* space and stores them in struct drm_shadow_plane_state.map. The
|
|
||||||
* framebuffer will be synchronized as part of the atomic commit.
|
|
||||||
*
|
*
|
||||||
* See drm_gem_simple_kms_cleanup_shadow_fb() for cleanup.
|
* See drm_gem_begin_shadow_fb_access() for details and
|
||||||
|
* drm_gem_simple_kms_cleanup_shadow_fb() for cleanup.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* 0 on success, or a negative errno code otherwise.
|
* 0 on success, or a negative errno code otherwise.
|
||||||
|
@ -436,14 +434,15 @@ int drm_gem_simple_kms_prepare_shadow_fb(struct drm_simple_display_pipe *pipe,
|
||||||
EXPORT_SYMBOL(drm_gem_simple_kms_prepare_shadow_fb);
|
EXPORT_SYMBOL(drm_gem_simple_kms_prepare_shadow_fb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_gem_simple_kms_cleanup_shadow_fb - releases shadow framebuffers
|
* drm_gem_simple_kms_end_shadow_fb_access - releases shadow framebuffers from CPU access
|
||||||
* @pipe: the simple display pipe
|
* @pipe: the simple display pipe
|
||||||
* @plane_state: the plane state of type struct drm_shadow_plane_state
|
* @plane_state: the plane state of type struct drm_shadow_plane_state
|
||||||
*
|
*
|
||||||
* This function implements struct drm_simple_display_funcs.cleanup_fb.
|
* This function implements struct drm_simple_display_funcs.end_fb_access.
|
||||||
* This function unmaps all buffer objects of the plane's framebuffer.
|
* It undoes all effects of drm_gem_simple_kms_begin_shadow_fb_access() in
|
||||||
|
* reverse order.
|
||||||
*
|
*
|
||||||
* See drm_gem_simple_kms_prepare_shadow_fb().
|
* See drm_gem_simple_kms_begin_shadow_fb_access().
|
||||||
*/
|
*/
|
||||||
void drm_gem_simple_kms_cleanup_shadow_fb(struct drm_simple_display_pipe *pipe,
|
void drm_gem_simple_kms_cleanup_shadow_fb(struct drm_simple_display_pipe *pipe,
|
||||||
struct drm_plane_state *plane_state)
|
struct drm_plane_state *plane_state)
|
||||||
|
|
|
@ -285,6 +285,30 @@ static void drm_simple_kms_plane_cleanup_fb(struct drm_plane *plane,
|
||||||
pipe->funcs->cleanup_fb(pipe, state);
|
pipe->funcs->cleanup_fb(pipe, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int drm_simple_kms_plane_begin_fb_access(struct drm_plane *plane,
|
||||||
|
struct drm_plane_state *new_plane_state)
|
||||||
|
{
|
||||||
|
struct drm_simple_display_pipe *pipe;
|
||||||
|
|
||||||
|
pipe = container_of(plane, struct drm_simple_display_pipe, plane);
|
||||||
|
if (!pipe->funcs || !pipe->funcs->begin_fb_access)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return pipe->funcs->begin_fb_access(pipe, new_plane_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drm_simple_kms_plane_end_fb_access(struct drm_plane *plane,
|
||||||
|
struct drm_plane_state *new_plane_state)
|
||||||
|
{
|
||||||
|
struct drm_simple_display_pipe *pipe;
|
||||||
|
|
||||||
|
pipe = container_of(plane, struct drm_simple_display_pipe, plane);
|
||||||
|
if (!pipe->funcs || !pipe->funcs->end_fb_access)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pipe->funcs->end_fb_access(pipe, new_plane_state);
|
||||||
|
}
|
||||||
|
|
||||||
static bool drm_simple_kms_format_mod_supported(struct drm_plane *plane,
|
static bool drm_simple_kms_format_mod_supported(struct drm_plane *plane,
|
||||||
uint32_t format,
|
uint32_t format,
|
||||||
uint64_t modifier)
|
uint64_t modifier)
|
||||||
|
@ -295,6 +319,8 @@ static bool drm_simple_kms_format_mod_supported(struct drm_plane *plane,
|
||||||
static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = {
|
static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = {
|
||||||
.prepare_fb = drm_simple_kms_plane_prepare_fb,
|
.prepare_fb = drm_simple_kms_plane_prepare_fb,
|
||||||
.cleanup_fb = drm_simple_kms_plane_cleanup_fb,
|
.cleanup_fb = drm_simple_kms_plane_cleanup_fb,
|
||||||
|
.begin_fb_access = drm_simple_kms_plane_begin_fb_access,
|
||||||
|
.end_fb_access = drm_simple_kms_plane_end_fb_access,
|
||||||
.atomic_check = drm_simple_kms_plane_atomic_check,
|
.atomic_check = drm_simple_kms_plane_atomic_check,
|
||||||
.atomic_update = drm_simple_kms_plane_atomic_update,
|
.atomic_update = drm_simple_kms_plane_atomic_update,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1184,11 +1184,20 @@ struct drm_plane_helper_funcs {
|
||||||
* can call drm_gem_plane_helper_prepare_fb() from their @prepare_fb
|
* can call drm_gem_plane_helper_prepare_fb() from their @prepare_fb
|
||||||
* hook.
|
* hook.
|
||||||
*
|
*
|
||||||
|
* The resources acquired in @prepare_fb persist after the end of
|
||||||
|
* the atomic commit. Resources that can be release at the commit's end
|
||||||
|
* should be acquired in @begin_fb_access and released in @end_fb_access.
|
||||||
|
* For example, a GEM buffer's pin operation belongs into @prepare_fb to
|
||||||
|
* keep the buffer pinned after the commit. But a vmap operation for
|
||||||
|
* shadow-plane helpers belongs into @begin_fb_access, so that atomic
|
||||||
|
* helpers remove the mapping at the end of the commit.
|
||||||
|
*
|
||||||
* The helpers will call @cleanup_fb with matching arguments for every
|
* The helpers will call @cleanup_fb with matching arguments for every
|
||||||
* successful call to this hook.
|
* successful call to this hook.
|
||||||
*
|
*
|
||||||
* This callback is used by the atomic modeset helpers and by the
|
* This callback is used by the atomic modeset helpers and by the
|
||||||
* transitional plane helpers, but it is optional.
|
* transitional plane helpers, but it is optional. See @begin_fb_access
|
||||||
|
* for preparing per-commit resources.
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
*
|
*
|
||||||
|
@ -1211,6 +1220,36 @@ struct drm_plane_helper_funcs {
|
||||||
void (*cleanup_fb)(struct drm_plane *plane,
|
void (*cleanup_fb)(struct drm_plane *plane,
|
||||||
struct drm_plane_state *old_state);
|
struct drm_plane_state *old_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @begin_fb_access:
|
||||||
|
*
|
||||||
|
* This hook prepares the plane for access during an atomic commit.
|
||||||
|
* In contrast to @prepare_fb, resources acquired in @begin_fb_access,
|
||||||
|
* are released at the end of the atomic commit in @end_fb_access.
|
||||||
|
*
|
||||||
|
* For example, with shadow-plane helpers, the GEM buffer's vmap
|
||||||
|
* operation belongs into @begin_fb_access, so that the buffer's
|
||||||
|
* memory will be unmapped at the end of the commit in @end_fb_access.
|
||||||
|
* But a GEM buffer's pin operation belongs into @prepare_fb
|
||||||
|
* to keep the buffer pinned after the commit.
|
||||||
|
*
|
||||||
|
* The callback is used by the atomic modeset helpers, but it is optional.
|
||||||
|
* See @end_fb_cleanup for undoing the effects of @begin_fb_access and
|
||||||
|
* @prepare_fb for acquiring resources until the next pageflip.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0 on success, or a negative errno code otherwise.
|
||||||
|
*/
|
||||||
|
int (*begin_fb_access)(struct drm_plane *plane, struct drm_plane_state *new_plane_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @end_fb_access:
|
||||||
|
*
|
||||||
|
* This hook cleans up resources allocated by @begin_fb_access. It it called
|
||||||
|
* at the end of a commit for the new plane state.
|
||||||
|
*/
|
||||||
|
void (*end_fb_access)(struct drm_plane *plane, struct drm_plane_state *new_plane_state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @atomic_check:
|
* @atomic_check:
|
||||||
*
|
*
|
||||||
|
|
|
@ -135,6 +135,26 @@ struct drm_simple_display_pipe_funcs {
|
||||||
void (*cleanup_fb)(struct drm_simple_display_pipe *pipe,
|
void (*cleanup_fb)(struct drm_simple_display_pipe *pipe,
|
||||||
struct drm_plane_state *plane_state);
|
struct drm_plane_state *plane_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @begin_fb_access:
|
||||||
|
*
|
||||||
|
* Optional, called by &drm_plane_helper_funcs.begin_fb_access. Please read
|
||||||
|
* the documentation for the &drm_plane_helper_funcs.begin_fb_access hook for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
int (*begin_fb_access)(struct drm_simple_display_pipe *pipe,
|
||||||
|
struct drm_plane_state *new_plane_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @end_fb_access:
|
||||||
|
*
|
||||||
|
* Optional, called by &drm_plane_helper_funcs.end_fb_access. Please read
|
||||||
|
* the documentation for the &drm_plane_helper_funcs.end_fb_access hook for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
void (*end_fb_access)(struct drm_simple_display_pipe *pipe,
|
||||||
|
struct drm_plane_state *plane_state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enable_vblank:
|
* @enable_vblank:
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Reference in a new issue