Skip to content

Commit 9dc9067

Browse files
author
Thomas Zimmermann
committed
drm/gem: Export helpers for shadow-buffered planes
Export the helpers for shadow-buffered planes. These will be used by several drivers. v3: * fix documentation typos and formatting (Daniel) Signed-off-by: Thomas Zimmermann <[email protected]> Reviewed-by: Daniel Vetter <[email protected]> Tested-by: Hans de Goede <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 9dd55df commit 9dc9067

File tree

2 files changed

+174
-6
lines changed

2 files changed

+174
-6
lines changed

drivers/gpu/drm/drm_gem_atomic_helper.c

Lines changed: 142 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,101 @@
1414
* functions for drivers that use GEM objects. Currently, it provides
1515
* plane state and framebuffer BO mappings for planes with shadow
1616
* buffers.
17+
*
18+
* A driver using a shadow buffer copies the content of the shadow buffers
19+
* into the HW's framebuffer memory during an atomic update. This requires
20+
* a mapping of the shadow buffer into kernel address space. The mappings
21+
* cannot be established by commit-tail functions, such as atomic_update,
22+
* as this would violate locking rules around dma_buf_vmap().
23+
*
24+
* The helpers for shadow-buffered planes establish and release mappings,
25+
* and provide struct drm_shadow_plane_state, which stores the plane's mapping
26+
* for commit-tail functons.
27+
*
28+
* Shadow-buffered planes can easily be enabled by using the provided macros
29+
* %DRM_GEM_SHADOW_PLANE_FUNCS and %DRM_GEM_SHADOW_PLANE_HELPER_FUNCS.
30+
* These macros set up the plane and plane-helper callbacks to point to the
31+
* shadow-buffer helpers.
32+
*
33+
* .. code-block:: c
34+
*
35+
* #include <drm/drm/gem_atomic_helper.h>
36+
*
37+
* struct drm_plane_funcs driver_plane_funcs = {
38+
* ...,
39+
* DRM_GEM_SHADOW_PLANE_FUNCS,
40+
* };
41+
*
42+
* struct drm_plane_helper_funcs driver_plane_helper_funcs = {
43+
* ...,
44+
* DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
45+
* };
46+
*
47+
* In the driver's atomic-update function, shadow-buffer mappings are available
48+
* from the plane state. Use to_drm_shadow_plane_state() to upcast from
49+
* struct drm_plane_state.
50+
*
51+
* .. code-block:: c
52+
*
53+
* void driver_plane_atomic_update(struct drm_plane *plane,
54+
* struct drm_plane_state *old_plane_state)
55+
* {
56+
* struct drm_plane_state *plane_state = plane->state;
57+
* struct drm_shadow_plane_state *shadow_plane_state =
58+
* to_drm_shadow_plane_state(plane_state);
59+
*
60+
* // access shadow buffer via shadow_plane_state->map
61+
* }
62+
*
63+
* A mapping address for each of the framebuffer's buffer object is stored in
64+
* struct &drm_shadow_plane_state.map. The mappings are valid while the state
65+
* is being used.
66+
*
67+
* Drivers that use struct drm_simple_display_pipe can use
68+
* %DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS to initialize the rsp
69+
* callbacks. Access to shadow-buffer mappings is similar to regular
70+
* atomic_update.
71+
*
72+
* .. code-block:: c
73+
*
74+
* struct drm_simple_display_pipe_funcs driver_pipe_funcs = {
75+
* ...,
76+
* DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
77+
* };
78+
*
79+
* void driver_pipe_enable(struct drm_simple_display_pipe *pipe,
80+
* struct drm_crtc_state *crtc_state,
81+
* struct drm_plane_state *plane_state)
82+
* {
83+
* struct drm_shadow_plane_state *shadow_plane_state =
84+
* to_drm_shadow_plane_state(plane_state);
85+
*
86+
* // access shadow buffer via shadow_plane_state->map
87+
* }
1788
*/
1889

1990
/*
2091
* Shadow-buffered Planes
2192
*/
2293

23-
static struct drm_plane_state *
94+
/**
95+
* drm_gem_duplicate_shadow_plane_state - duplicates shadow-buffered plane state
96+
* @plane: the plane
97+
*
98+
* This function implements struct &drm_plane_funcs.atomic_duplicate_state for
99+
* shadow-buffered planes. It assumes the existing state to be of type
100+
* struct drm_shadow_plane_state and it allocates the new state to be of this
101+
* type.
102+
*
103+
* The function does not duplicate existing mappings of the shadow buffers.
104+
* Mappings are maintained during the atomic commit by the plane's prepare_fb
105+
* and cleanup_fb helpers. See drm_gem_prepare_shadow_fb() and drm_gem_cleanup_shadow_fb()
106+
* for corresponding helpers.
107+
*
108+
* Returns:
109+
* A pointer to a new plane state on success, or NULL otherwise.
110+
*/
111+
struct drm_plane_state *
24112
drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane)
25113
{
26114
struct drm_plane_state *plane_state = plane->state;
@@ -36,18 +124,38 @@ drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane)
36124

37125
return &new_shadow_plane_state->base;
38126
}
127+
EXPORT_SYMBOL(drm_gem_duplicate_shadow_plane_state);
39128

40-
static void drm_gem_destroy_shadow_plane_state(struct drm_plane *plane,
41-
struct drm_plane_state *plane_state)
129+
/**
130+
* drm_gem_destroy_shadow_plane_state - deletes shadow-buffered plane state
131+
* @plane: the plane
132+
* @plane_state: the plane state of type struct drm_shadow_plane_state
133+
*
134+
* This function implements struct &drm_plane_funcs.atomic_destroy_state
135+
* for shadow-buffered planes. It expects that mappings of shadow buffers
136+
* have been released already.
137+
*/
138+
void drm_gem_destroy_shadow_plane_state(struct drm_plane *plane,
139+
struct drm_plane_state *plane_state)
42140
{
43141
struct drm_shadow_plane_state *shadow_plane_state =
44142
to_drm_shadow_plane_state(plane_state);
45143

46144
__drm_atomic_helper_plane_destroy_state(&shadow_plane_state->base);
47145
kfree(shadow_plane_state);
48146
}
147+
EXPORT_SYMBOL(drm_gem_destroy_shadow_plane_state);
49148

50-
static void drm_gem_reset_shadow_plane(struct drm_plane *plane)
149+
/**
150+
* drm_gem_reset_shadow_plane - resets a shadow-buffered plane
151+
* @plane: the plane
152+
*
153+
* This function implements struct &drm_plane_funcs.reset_plane for
154+
* shadow-buffered planes. It assumes the current plane state to be
155+
* of type struct drm_shadow_plane and it allocates the new state of
156+
* this type.
157+
*/
158+
void drm_gem_reset_shadow_plane(struct drm_plane *plane)
51159
{
52160
struct drm_shadow_plane_state *shadow_plane_state;
53161

@@ -61,8 +169,24 @@ static void drm_gem_reset_shadow_plane(struct drm_plane *plane)
61169
return;
62170
__drm_atomic_helper_plane_reset(plane, &shadow_plane_state->base);
63171
}
172+
EXPORT_SYMBOL(drm_gem_reset_shadow_plane);
64173

65-
static int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state)
174+
/**
175+
* drm_gem_prepare_shadow_fb - prepares shadow framebuffers
176+
* @plane: the plane
177+
* @plane_state: the plane state of type struct drm_shadow_plane_state
178+
*
179+
* This function implements struct &drm_plane_helper_funcs.prepare_fb. It
180+
* maps all buffer objects of the plane's framebuffer into kernel address
181+
* space and stores them in &struct drm_shadow_plane_state.map. The
182+
* framebuffer will be synchronized as part of the atomic commit.
183+
*
184+
* See drm_gem_cleanup_shadow_fb() for cleanup.
185+
*
186+
* Returns:
187+
* 0 on success, or a negative errno code otherwise.
188+
*/
189+
int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state)
66190
{
67191
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
68192
struct drm_framebuffer *fb = plane_state->fb;
@@ -100,8 +224,19 @@ static int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_s
100224
}
101225
return ret;
102226
}
227+
EXPORT_SYMBOL(drm_gem_prepare_shadow_fb);
103228

104-
static void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state)
229+
/**
230+
* drm_gem_cleanup_shadow_fb - releases shadow framebuffers
231+
* @plane: the plane
232+
* @plane_state: the plane state of type struct drm_shadow_plane_state
233+
*
234+
* This function implements struct &drm_plane_helper_funcs.cleanup_fb.
235+
* This function unmaps all buffer objects of the plane's framebuffer.
236+
*
237+
* See drm_gem_prepare_shadow_fb() for more inforamtion.
238+
*/
239+
void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state)
105240
{
106241
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
107242
struct drm_framebuffer *fb = plane_state->fb;
@@ -119,6 +254,7 @@ static void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_
119254
drm_gem_vunmap(obj, &shadow_plane_state->map[i]);
120255
}
121256
}
257+
EXPORT_SYMBOL(drm_gem_cleanup_shadow_fb);
122258

123259
/**
124260
* drm_gem_simple_kms_prepare_shadow_fb - prepares shadow framebuffers

include/drm/drm_gem_atomic_helper.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,38 @@ to_drm_shadow_plane_state(struct drm_plane_state *state)
4545
return container_of(state, struct drm_shadow_plane_state, base);
4646
}
4747

48+
void drm_gem_reset_shadow_plane(struct drm_plane *plane);
49+
struct drm_plane_state *drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane);
50+
void drm_gem_destroy_shadow_plane_state(struct drm_plane *plane,
51+
struct drm_plane_state *plane_state);
52+
53+
/**
54+
* DRM_GEM_SHADOW_PLANE_FUNCS -
55+
* Initializes struct drm_plane_funcs for shadow-buffered planes
56+
*
57+
* Drivers may use GEM BOs as shadow buffers over the framebuffer memory. This
58+
* macro initializes struct drm_plane_funcs to use the rsp helper functions.
59+
*/
60+
#define DRM_GEM_SHADOW_PLANE_FUNCS \
61+
.reset = drm_gem_reset_shadow_plane, \
62+
.atomic_duplicate_state = drm_gem_duplicate_shadow_plane_state, \
63+
.atomic_destroy_state = drm_gem_destroy_shadow_plane_state
64+
65+
int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state);
66+
void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state);
67+
68+
/**
69+
* DRM_GEM_SHADOW_PLANE_HELPER_FUNCS -
70+
* Initializes struct drm_plane_helper_funcs for shadow-buffered planes
71+
*
72+
* Drivers may use GEM BOs as shadow buffers over the framebuffer memory. This
73+
* macro initializes struct drm_plane_helper_funcs to use the rsp helper
74+
* functions.
75+
*/
76+
#define DRM_GEM_SHADOW_PLANE_HELPER_FUNCS \
77+
.prepare_fb = drm_gem_prepare_shadow_fb, \
78+
.cleanup_fb = drm_gem_cleanup_shadow_fb
79+
4880
int drm_gem_simple_kms_prepare_shadow_fb(struct drm_simple_display_pipe *pipe,
4981
struct drm_plane_state *plane_state);
5082
void drm_gem_simple_kms_cleanup_shadow_fb(struct drm_simple_display_pipe *pipe,

0 commit comments

Comments
 (0)