This new IOCTL allows callers to close a framebuffer without disabling planes or CRTCs. This takes inspiration from Rob Clark's unref_fb IOCTL [1] and DRM_MODE_FB_PERSIST [2]. User-space patch for wlroots available at [3]. IGT test available at [4]. v2: add an extra pad field just in case we want to extend this IOCTL in the future (Pekka, Sima). [1]: https://lore.kernel.org/dri-devel/20170509153654.23464-1-robdclark@gmail.com/ [2]: https://lore.kernel.org/dri-devel/20211006151921.312714-1-contact@emersion.fr/ [3]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4394 [4]: https://lists.freedesktop.org/archives/igt-dev/2023-October/063294.html
Unified · Split
| @@ -222,6 +222,8 @@ int drm_mode_addfb2_ioctl(struct drm_device *dev, · 221 unmodified lines | ||
| 222 | 222 | void *data, struct drm_file *file_priv); |
| 223 | 223 | int drm_mode_rmfb_ioctl(struct drm_device *dev, |
| 224 | 224 | void *data, struct drm_file *file_priv); |
| 225 | +int drm_mode_closefb_ioctl(struct drm_device *dev, | |
| 226 | + void *data, struct drm_file *file_priv); | |
| 225 | 227 | int drm_mode_getfb(struct drm_device *dev, |
| 226 | 228 | void *data, struct drm_file *file_priv); |
| 227 | 229 | int drm_mode_getfb2_ioctl(struct drm_device *dev, |
| @@ -480,6 +480,28 @@ int drm_mode_rmfb_ioctl(struct drm_device *dev, · 479 unmodified lines | ||
| 480 | 480 | return drm_mode_rmfb(dev, *fb_id, file_priv); |
| 481 | 481 | } |
| 482 | 482 | |
| 483 | +int drm_mode_closefb_ioctl(struct drm_device *dev, | |
| 484 | + void *data, struct drm_file *file_priv) | |
| 485 | +{ | |
| 486 | + struct drm_mode_closefb *r = data; | |
| 487 | + struct drm_framebuffer *fb; | |
| 488 | + int ret; | |
| 489 | + | |
| 490 | + if (!drm_core_check_feature(dev, DRIVER_MODESET)) | |
| 491 | + return -EOPNOTSUPP; | |
| 492 | + | |
| 493 | + if (r->pad) | |
| 494 | + return -EINVAL; | |
| 495 | + | |
| 496 | + fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id); | |
| 497 | + if (!fb) | |
| 498 | + return -ENOENT; | |
| 499 | + | |
| 500 | + ret = drm_mode_closefb(fb, file_priv); | |
| 501 | + drm_framebuffer_put(fb); | |
| 502 | + return ret; | |
| 503 | +} | |
| 504 | + | |
| 483 | 505 | /** |
| 484 | 506 | * drm_mode_getfb - get FB info |
| 485 | 507 | * @dev: drm device for the ioctl |
| @@ -675,6 +675,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { · 674 unmodified lines | ||
| 675 | 675 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb_ioctl, 0), |
| 676 | 676 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2_ioctl, 0), |
| 677 | 677 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb_ioctl, 0), |
| 678 | + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CLOSEFB, drm_mode_closefb_ioctl, 0), | |
| 678 | 679 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER), |
| 679 | 680 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER), |
| 680 | 681 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, 0), |
| @@ -1218,6 +1218,26 @@ extern "C" { · 1217 unmodified lines | ||
| 1218 | 1218 | |
| 1219 | 1219 | #define DRM_IOCTL_SYNCOBJ_EVENTFD DRM_IOWR(0xCF, struct drm_syncobj_eventfd) |
| 1220 | 1220 | |
| 1221 | +/** | |
| 1222 | + * DRM_IOCTL_MODE_CLOSEFB - Close a framebuffer. | |
| 1223 | + * | |
| 1224 | + * This closes a framebuffer previously added via ADDFB/ADDFB2. The IOCTL | |
| 1225 | + * argument is a framebuffer object ID. | |
| 1226 | + * | |
| 1227 | + * This IOCTL is similar to &DRM_IOCTL_MODE_RMFB, except it doesn't disable | |
| 1228 | + * planes and CRTCs. As long as the framebuffer is used by a plane, it's kept | |
| 1229 | + * alive. When the plane no longer uses the framebuffer (because the | |
| 1230 | + * framebuffer is replaced with another one, or the plane is disabled), the | |
| 1231 | + * framebuffer is cleaned up. | |
| 1232 | + * | |
| 1233 | + * This is useful to implement flicker-free transitions between two processes. | |
| 1234 | + * | |
| 1235 | + * Depending on the threat model, user-space may want to ensure that the | |
| 1236 | + * framebuffer doesn't expose any sensitive user information: closed | |
| 1237 | + * framebuffers attached to a plane can be read back by the next DRM master. | |
| 1238 | + */ | |
| 1239 | +#define DRM_IOCTL_MODE_CLOSEFB DRM_IOWR(0xD0, struct drm_mode_closefb) | |
| 1240 | + | |
| 1221 | 1241 | /* |
| 1222 | 1242 | * Device specific ioctls should only be in their respective headers |
| 1223 | 1243 | * The device specific ioctl range is from 0x40 to 0x9f. |
| @@ -1323,6 +1323,16 @@ struct drm_mode_rect { · 1322 unmodified lines | ||
| 1323 | 1323 | __s32 y2; |
| 1324 | 1324 | }; |
| 1325 | 1325 | |
| 1326 | +/** | |
| 1327 | + * struct drm_mode_closefb | |
| 1328 | + * @fb_id: Framebuffer ID. | |
| 1329 | + * @pad: Must be zero. | |
| 1330 | + */ | |
| 1331 | +struct drm_mode_closefb { | |
| 1332 | + __u32 fb_id; | |
| 1333 | + __u32 pad; | |
| 1334 | +}; | |
| 1335 | + | |
| 1326 | 1336 | #if defined(__cplusplus) |
| 1327 | 1337 | } |
| 1328 | 1338 | #endif |