Skip to content

Commit 94d879e

Browse files
author
Thomas Zimmermann
committed
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 <[email protected]> Reviewed-by: Javier Martinez Canillas <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 260cd59 commit 94d879e

File tree

5 files changed

+126
-14
lines changed

5 files changed

+126
-14
lines changed

drivers/gpu/drm/drm_atomic_helper.c

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2536,7 +2536,7 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
25362536
if (funcs->prepare_fb) {
25372537
ret = funcs->prepare_fb(plane, new_plane_state);
25382538
if (ret)
2539-
goto fail;
2539+
goto fail_prepare_fb;
25402540
} else {
25412541
WARN_ON_ONCE(funcs->cleanup_fb);
25422542

@@ -2545,13 +2545,34 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
25452545

25462546
ret = drm_gem_plane_helper_prepare_fb(plane, new_plane_state);
25472547
if (ret)
2548-
goto fail;
2548+
goto fail_prepare_fb;
2549+
}
2550+
}
2551+
2552+
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
2553+
const struct drm_plane_helper_funcs *funcs = plane->helper_private;
2554+
2555+
if (funcs->begin_fb_access) {
2556+
ret = funcs->begin_fb_access(plane, new_plane_state);
2557+
if (ret)
2558+
goto fail_begin_fb_access;
25492559
}
25502560
}
25512561

25522562
return 0;
25532563

2554-
fail:
2564+
fail_begin_fb_access:
2565+
for_each_new_plane_in_state(state, plane, new_plane_state, j) {
2566+
const struct drm_plane_helper_funcs *funcs = plane->helper_private;
2567+
2568+
if (j >= i)
2569+
continue;
2570+
2571+
if (funcs->end_fb_access)
2572+
funcs->end_fb_access(plane, new_plane_state);
2573+
}
2574+
i = j; /* set i to upper limit to cleanup all planes */
2575+
fail_prepare_fb:
25552576
for_each_new_plane_in_state(state, plane, new_plane_state, j) {
25562577
const struct drm_plane_helper_funcs *funcs;
25572578

@@ -2827,6 +2848,13 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
28272848
struct drm_plane_state *old_plane_state, *new_plane_state;
28282849
int i;
28292850

2851+
for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
2852+
const struct drm_plane_helper_funcs *funcs = plane->helper_private;
2853+
2854+
if (funcs->end_fb_access)
2855+
funcs->end_fb_access(plane, new_plane_state);
2856+
}
2857+
28302858
for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
28312859
const struct drm_plane_helper_funcs *funcs;
28322860
struct drm_plane_state *plane_state;

drivers/gpu/drm/drm_gem_atomic_helper.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -414,16 +414,14 @@ void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *
414414
EXPORT_SYMBOL(drm_gem_cleanup_shadow_fb);
415415

416416
/**
417-
* drm_gem_simple_kms_prepare_shadow_fb - prepares shadow framebuffers
417+
* drm_gem_simple_kms_begin_shadow_fb_access - prepares shadow framebuffers for CPU access
418418
* @pipe: the simple display pipe
419419
* @plane_state: the plane state of type struct drm_shadow_plane_state
420420
*
421-
* This function implements struct drm_simple_display_funcs.prepare_fb. It
422-
* maps all buffer objects of the plane's framebuffer into kernel address
423-
* space and stores them in struct drm_shadow_plane_state.map. The
424-
* framebuffer will be synchronized as part of the atomic commit.
421+
* This function implements struct drm_simple_display_funcs.begin_fb_access.
425422
*
426-
* See drm_gem_simple_kms_cleanup_shadow_fb() for cleanup.
423+
* See drm_gem_begin_shadow_fb_access() for details and
424+
* drm_gem_simple_kms_cleanup_shadow_fb() for cleanup.
427425
*
428426
* Returns:
429427
* 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,
436434
EXPORT_SYMBOL(drm_gem_simple_kms_prepare_shadow_fb);
437435

438436
/**
439-
* drm_gem_simple_kms_cleanup_shadow_fb - releases shadow framebuffers
437+
* drm_gem_simple_kms_end_shadow_fb_access - releases shadow framebuffers from CPU access
440438
* @pipe: the simple display pipe
441439
* @plane_state: the plane state of type struct drm_shadow_plane_state
442440
*
443-
* This function implements struct drm_simple_display_funcs.cleanup_fb.
444-
* This function unmaps all buffer objects of the plane's framebuffer.
441+
* This function implements struct drm_simple_display_funcs.end_fb_access.
442+
* It undoes all effects of drm_gem_simple_kms_begin_shadow_fb_access() in
443+
* reverse order.
445444
*
446-
* See drm_gem_simple_kms_prepare_shadow_fb().
445+
* See drm_gem_simple_kms_begin_shadow_fb_access().
447446
*/
448447
void drm_gem_simple_kms_cleanup_shadow_fb(struct drm_simple_display_pipe *pipe,
449448
struct drm_plane_state *plane_state)

drivers/gpu/drm/drm_simple_kms_helper.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,30 @@ static void drm_simple_kms_plane_cleanup_fb(struct drm_plane *plane,
285285
pipe->funcs->cleanup_fb(pipe, state);
286286
}
287287

288+
static int drm_simple_kms_plane_begin_fb_access(struct drm_plane *plane,
289+
struct drm_plane_state *new_plane_state)
290+
{
291+
struct drm_simple_display_pipe *pipe;
292+
293+
pipe = container_of(plane, struct drm_simple_display_pipe, plane);
294+
if (!pipe->funcs || !pipe->funcs->begin_fb_access)
295+
return 0;
296+
297+
return pipe->funcs->begin_fb_access(pipe, new_plane_state);
298+
}
299+
300+
static void drm_simple_kms_plane_end_fb_access(struct drm_plane *plane,
301+
struct drm_plane_state *new_plane_state)
302+
{
303+
struct drm_simple_display_pipe *pipe;
304+
305+
pipe = container_of(plane, struct drm_simple_display_pipe, plane);
306+
if (!pipe->funcs || !pipe->funcs->end_fb_access)
307+
return;
308+
309+
pipe->funcs->end_fb_access(pipe, new_plane_state);
310+
}
311+
288312
static bool drm_simple_kms_format_mod_supported(struct drm_plane *plane,
289313
uint32_t format,
290314
uint64_t modifier)
@@ -295,6 +319,8 @@ static bool drm_simple_kms_format_mod_supported(struct drm_plane *plane,
295319
static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = {
296320
.prepare_fb = drm_simple_kms_plane_prepare_fb,
297321
.cleanup_fb = drm_simple_kms_plane_cleanup_fb,
322+
.begin_fb_access = drm_simple_kms_plane_begin_fb_access,
323+
.end_fb_access = drm_simple_kms_plane_end_fb_access,
298324
.atomic_check = drm_simple_kms_plane_atomic_check,
299325
.atomic_update = drm_simple_kms_plane_atomic_update,
300326
};

include/drm/drm_modeset_helper_vtables.h

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1184,11 +1184,20 @@ struct drm_plane_helper_funcs {
11841184
* can call drm_gem_plane_helper_prepare_fb() from their @prepare_fb
11851185
* hook.
11861186
*
1187+
* The resources acquired in @prepare_fb persist after the end of
1188+
* the atomic commit. Resources that can be release at the commit's end
1189+
* should be acquired in @begin_fb_access and released in @end_fb_access.
1190+
* For example, a GEM buffer's pin operation belongs into @prepare_fb to
1191+
* keep the buffer pinned after the commit. But a vmap operation for
1192+
* shadow-plane helpers belongs into @begin_fb_access, so that atomic
1193+
* helpers remove the mapping at the end of the commit.
1194+
*
11871195
* The helpers will call @cleanup_fb with matching arguments for every
11881196
* successful call to this hook.
11891197
*
11901198
* This callback is used by the atomic modeset helpers and by the
1191-
* transitional plane helpers, but it is optional.
1199+
* transitional plane helpers, but it is optional. See @begin_fb_access
1200+
* for preparing per-commit resources.
11921201
*
11931202
* RETURNS:
11941203
*
@@ -1211,6 +1220,36 @@ struct drm_plane_helper_funcs {
12111220
void (*cleanup_fb)(struct drm_plane *plane,
12121221
struct drm_plane_state *old_state);
12131222

1223+
/**
1224+
* @begin_fb_access:
1225+
*
1226+
* This hook prepares the plane for access during an atomic commit.
1227+
* In contrast to @prepare_fb, resources acquired in @begin_fb_access,
1228+
* are released at the end of the atomic commit in @end_fb_access.
1229+
*
1230+
* For example, with shadow-plane helpers, the GEM buffer's vmap
1231+
* operation belongs into @begin_fb_access, so that the buffer's
1232+
* memory will be unmapped at the end of the commit in @end_fb_access.
1233+
* But a GEM buffer's pin operation belongs into @prepare_fb
1234+
* to keep the buffer pinned after the commit.
1235+
*
1236+
* The callback is used by the atomic modeset helpers, but it is optional.
1237+
* See @end_fb_cleanup for undoing the effects of @begin_fb_access and
1238+
* @prepare_fb for acquiring resources until the next pageflip.
1239+
*
1240+
* Returns:
1241+
* 0 on success, or a negative errno code otherwise.
1242+
*/
1243+
int (*begin_fb_access)(struct drm_plane *plane, struct drm_plane_state *new_plane_state);
1244+
1245+
/**
1246+
* @end_fb_access:
1247+
*
1248+
* This hook cleans up resources allocated by @begin_fb_access. It it called
1249+
* at the end of a commit for the new plane state.
1250+
*/
1251+
void (*end_fb_access)(struct drm_plane *plane, struct drm_plane_state *new_plane_state);
1252+
12141253
/**
12151254
* @atomic_check:
12161255
*

include/drm/drm_simple_kms_helper.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,26 @@ struct drm_simple_display_pipe_funcs {
135135
void (*cleanup_fb)(struct drm_simple_display_pipe *pipe,
136136
struct drm_plane_state *plane_state);
137137

138+
/**
139+
* @begin_fb_access:
140+
*
141+
* Optional, called by &drm_plane_helper_funcs.begin_fb_access. Please read
142+
* the documentation for the &drm_plane_helper_funcs.begin_fb_access hook for
143+
* more details.
144+
*/
145+
int (*begin_fb_access)(struct drm_simple_display_pipe *pipe,
146+
struct drm_plane_state *new_plane_state);
147+
148+
/**
149+
* @end_fb_access:
150+
*
151+
* Optional, called by &drm_plane_helper_funcs.end_fb_access. Please read
152+
* the documentation for the &drm_plane_helper_funcs.end_fb_access hook for
153+
* more details.
154+
*/
155+
void (*end_fb_access)(struct drm_simple_display_pipe *pipe,
156+
struct drm_plane_state *plane_state);
157+
138158
/**
139159
* @enable_vblank:
140160
*

0 commit comments

Comments
 (0)