diff options
author | Rob Clark <robdclark@gmail.com> | 2018-05-30 20:46:20 -0400 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2018-12-05 04:00:37 -0500 |
commit | b9fc5e01d1ce78eb53fd4dedd51a1563e636eea2 (patch) | |
tree | f3be8f1c2b0785dbd7458315b74fd88eea432714 | |
parent | f13ba9c21dc8275207f3705dba37fff947347dca (diff) |
drm: Add helper to implement legacy dirtyfb
Add an atomic helper to implement dirtyfb support. This is needed to
support DSI command-mode panels with x11 userspace (ie. when we can't
rely on pageflips to trigger a flush to the panel).
v2: Modified the helper to use plane fb_damage_clips property and
removed plane_state::dirty flag.
v3:
- Use uapi drm_mode_rect.
- Support annotate flags.
v4: Correct kernel doc.
Signed-off-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Deepak Rawat <drawat@vmware.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
-rw-r--r-- | drivers/gpu/drm/drm_damage_helper.c | 126 | ||||
-rw-r--r-- | include/drm/drm_damage_helper.h | 4 |
2 files changed, 130 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c index f339b1481750..05c8e7267165 100644 --- a/drivers/gpu/drm/drm_damage_helper.c +++ b/drivers/gpu/drm/drm_damage_helper.c | |||
@@ -26,6 +26,7 @@ | |||
26 | * | 26 | * |
27 | * Authors: | 27 | * Authors: |
28 | * Deepak Rawat <drawat@vmware.com> | 28 | * Deepak Rawat <drawat@vmware.com> |
29 | * Rob Clark <robdclark@gmail.com> | ||
29 | * | 30 | * |
30 | **************************************************************************/ | 31 | **************************************************************************/ |
31 | 32 | ||
@@ -70,6 +71,21 @@ | |||
70 | * rectangles clipped to &drm_plane_state.src. | 71 | * rectangles clipped to &drm_plane_state.src. |
71 | */ | 72 | */ |
72 | 73 | ||
74 | static void convert_clip_rect_to_rect(const struct drm_clip_rect *src, | ||
75 | struct drm_mode_rect *dest, | ||
76 | uint32_t num_clips, uint32_t src_inc) | ||
77 | { | ||
78 | while (num_clips > 0) { | ||
79 | dest->x1 = src->x1; | ||
80 | dest->y1 = src->y1; | ||
81 | dest->x2 = src->x2; | ||
82 | dest->y2 = src->y2; | ||
83 | src += src_inc; | ||
84 | dest++; | ||
85 | num_clips--; | ||
86 | } | ||
87 | } | ||
88 | |||
73 | /** | 89 | /** |
74 | * drm_plane_enable_fb_damage_clips - Enables plane fb damage clips property. | 90 | * drm_plane_enable_fb_damage_clips - Enables plane fb damage clips property. |
75 | * @plane: Plane on which to enable damage clips property. | 91 | * @plane: Plane on which to enable damage clips property. |
@@ -121,6 +137,116 @@ void drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state, | |||
121 | EXPORT_SYMBOL(drm_atomic_helper_check_plane_damage); | 137 | EXPORT_SYMBOL(drm_atomic_helper_check_plane_damage); |
122 | 138 | ||
123 | /** | 139 | /** |
140 | * drm_atomic_helper_dirtyfb - Helper for dirtyfb. | ||
141 | * @fb: DRM framebuffer. | ||
142 | * @file_priv: Drm file for the ioctl call. | ||
143 | * @flags: Dirty fb annotate flags. | ||
144 | * @color: Color for annotate fill. | ||
145 | * @clips: Dirty region. | ||
146 | * @num_clips: Count of clip in clips. | ||
147 | * | ||
148 | * A helper to implement &drm_framebuffer_funcs.dirty using damage interface | ||
149 | * during plane update. If num_clips is 0 then this helper will do a full plane | ||
150 | * update. This is the same behaviour expected by DIRTFB IOCTL. | ||
151 | * | ||
152 | * Note that this helper is blocking implementation. This is what current | ||
153 | * drivers and userspace expect in their DIRTYFB IOCTL implementation, as a way | ||
154 | * to rate-limit userspace and make sure its rendering doesn't get ahead of | ||
155 | * uploading new data too much. | ||
156 | * | ||
157 | * Return: Zero on success, negative errno on failure. | ||
158 | */ | ||
159 | int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb, | ||
160 | struct drm_file *file_priv, unsigned int flags, | ||
161 | unsigned int color, struct drm_clip_rect *clips, | ||
162 | unsigned int num_clips) | ||
163 | { | ||
164 | struct drm_modeset_acquire_ctx ctx; | ||
165 | struct drm_property_blob *damage = NULL; | ||
166 | struct drm_mode_rect *rects = NULL; | ||
167 | struct drm_atomic_state *state; | ||
168 | struct drm_plane *plane; | ||
169 | int ret = 0; | ||
170 | |||
171 | /* | ||
172 | * When called from ioctl, we are interruptable, but not when called | ||
173 | * internally (ie. defio worker) | ||
174 | */ | ||
175 | drm_modeset_acquire_init(&ctx, | ||
176 | file_priv ? DRM_MODESET_ACQUIRE_INTERRUPTIBLE : 0); | ||
177 | |||
178 | state = drm_atomic_state_alloc(fb->dev); | ||
179 | if (!state) { | ||
180 | ret = -ENOMEM; | ||
181 | goto out; | ||
182 | } | ||
183 | state->acquire_ctx = &ctx; | ||
184 | |||
185 | if (clips) { | ||
186 | uint32_t inc = 1; | ||
187 | |||
188 | if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) { | ||
189 | inc = 2; | ||
190 | num_clips /= 2; | ||
191 | } | ||
192 | |||
193 | rects = kcalloc(num_clips, sizeof(*rects), GFP_KERNEL); | ||
194 | if (!rects) { | ||
195 | ret = -ENOMEM; | ||
196 | goto out; | ||
197 | } | ||
198 | |||
199 | convert_clip_rect_to_rect(clips, rects, num_clips, inc); | ||
200 | damage = drm_property_create_blob(fb->dev, | ||
201 | num_clips * sizeof(*rects), | ||
202 | rects); | ||
203 | if (IS_ERR(damage)) { | ||
204 | ret = PTR_ERR(damage); | ||
205 | damage = NULL; | ||
206 | goto out; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | retry: | ||
211 | drm_for_each_plane(plane, fb->dev) { | ||
212 | struct drm_plane_state *plane_state; | ||
213 | |||
214 | if (plane->state->fb != fb) | ||
215 | continue; | ||
216 | |||
217 | plane_state = drm_atomic_get_plane_state(state, plane); | ||
218 | if (IS_ERR(plane_state)) { | ||
219 | ret = PTR_ERR(plane_state); | ||
220 | goto out; | ||
221 | } | ||
222 | |||
223 | drm_property_replace_blob(&plane_state->fb_damage_clips, | ||
224 | damage); | ||
225 | } | ||
226 | |||
227 | ret = drm_atomic_commit(state); | ||
228 | |||
229 | out: | ||
230 | if (ret == -EDEADLK) { | ||
231 | drm_atomic_state_clear(state); | ||
232 | ret = drm_modeset_backoff(&ctx); | ||
233 | if (!ret) | ||
234 | goto retry; | ||
235 | } | ||
236 | |||
237 | drm_property_blob_put(damage); | ||
238 | kfree(rects); | ||
239 | drm_atomic_state_put(state); | ||
240 | |||
241 | drm_modeset_drop_locks(&ctx); | ||
242 | drm_modeset_acquire_fini(&ctx); | ||
243 | |||
244 | return ret; | ||
245 | |||
246 | } | ||
247 | EXPORT_SYMBOL(drm_atomic_helper_dirtyfb); | ||
248 | |||
249 | /** | ||
124 | * drm_atomic_helper_damage_iter_init - Initialize the damage iterator. | 250 | * drm_atomic_helper_damage_iter_init - Initialize the damage iterator. |
125 | * @iter: The iterator to initialize. | 251 | * @iter: The iterator to initialize. |
126 | * @old_state: Old plane state for validation. | 252 | * @old_state: Old plane state for validation. |
diff --git a/include/drm/drm_damage_helper.h b/include/drm/drm_damage_helper.h index b9a0d05fb093..4487660b26b8 100644 --- a/include/drm/drm_damage_helper.h +++ b/include/drm/drm_damage_helper.h | |||
@@ -67,6 +67,10 @@ struct drm_atomic_helper_damage_iter { | |||
67 | void drm_plane_enable_fb_damage_clips(struct drm_plane *plane); | 67 | void drm_plane_enable_fb_damage_clips(struct drm_plane *plane); |
68 | void drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state, | 68 | void drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state, |
69 | struct drm_plane_state *plane_state); | 69 | struct drm_plane_state *plane_state); |
70 | int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb, | ||
71 | struct drm_file *file_priv, unsigned int flags, | ||
72 | unsigned int color, struct drm_clip_rect *clips, | ||
73 | unsigned int num_clips); | ||
70 | void | 74 | void |
71 | drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter, | 75 | drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter, |
72 | const struct drm_plane_state *old_state, | 76 | const struct drm_plane_state *old_state, |