summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdrm/xf86drmMode.c21
-rw-r--r--libdrm/xf86drmMode.h6
-rw-r--r--linux-core/drm_crtc.c55
-rw-r--r--linux-core/drm_crtc.h3
-rw-r--r--linux-core/drm_drv.c2
-rw-r--r--shared-core/drm.h1
6 files changed, 85 insertions, 3 deletions
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c
index 605377dd..ae15fd65 100644
--- a/libdrm/xf86drmMode.c
+++ b/libdrm/xf86drmMode.c
@@ -608,3 +608,24 @@ int drmCheckModesettingSupported(const char *busid)
return -ENOSYS;
}
+
+int drmModeReplaceFB(int fd, uint32_t buffer_id,
+ uint32_t width, uint32_t height, uint8_t depth,
+ uint8_t bpp, uint32_t pitch, uint32_t bo_handle)
+{
+ struct drm_mode_fb_cmd f;
+ int ret;
+
+ f.width = width;
+ f.height = height;
+ f.pitch = pitch;
+ f.bpp = bpp;
+ f.depth = depth;
+ f.handle = bo_handle;
+ f.buffer_id = buffer_id;
+
+ if ((ret = ioctl(fd, DRM_IOCTL_MODE_REPLACEFB, &f)))
+ return ret;
+
+ return 0;
+}
diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h
index e5a6ee92..5171b592 100644
--- a/libdrm/xf86drmMode.h
+++ b/libdrm/xf86drmMode.h
@@ -184,6 +184,12 @@ extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
*/
extern int drmModeRmFB(int fd, uint32_t bufferId);
+/**
+ * Replace a framebuffer object with a new one - for resizing the screen.
+ */
+extern int drmModeReplaceFB(int fd, uint32_t buffer_id,
+ uint32_t width, uint32_t height, uint8_t depth,
+ uint8_t bpp, uint32_t pitch, uint32_t bo_handle);
/*
* Crtc functions
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c
index 1e5195db..60255f54 100644
--- a/linux-core/drm_crtc.c
+++ b/linux-core/drm_crtc.c
@@ -1879,8 +1879,8 @@ out:
int drm_mode_rmfb(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
- struct drm_framebuffer *fb = 0;
- struct drm_framebuffer *fbl = 0;
+ struct drm_framebuffer *fb = NULL;
+ struct drm_framebuffer *fbl = NULL;
uint32_t *id = data;
int ret = 0;
int found = 0;
@@ -2513,3 +2513,54 @@ out:
return ret;
}
+
+int drm_mode_replacefb(struct drm_device *dev,
+ void *data, struct drm_file *file_priv)
+{
+ struct drm_mode_fb_cmd *r = data;
+ struct drm_framebuffer *fb;
+ struct drm_crtc *crtc;
+ struct drm_buffer_object *bo;
+ int found = 0;
+ struct drm_framebuffer *fbl = NULL;
+ int ret = 0;
+ /* right replace the current bo attached to this fb with a new bo */
+ mutex_lock(&dev->mode_config.mutex);
+ ret = drm_get_buffer_object(dev, &bo, r->handle);
+ if (ret || !bo) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ fb = idr_find(&dev->mode_config.crtc_idr, r->buffer_id);
+ if (!fb || (r->buffer_id != fb->id)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ list_for_each_entry(fbl, &file_priv->fbs, filp_head)
+ if (fb == fbl)
+ found = 1;
+
+ if (!found) {
+ DRM_ERROR("tried to replace an fb we didn't own\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (fb->bo->type == drm_bo_type_kernel)
+ DRM_ERROR("the bo should not be a kernel bo\n");
+
+ fb->bo = bo;
+
+ /* find all crtcs connected to this fb */
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (crtc->fb->id == r->buffer_id) {
+ crtc->funcs->mode_set_base(crtc, crtc->x, crtc->y);
+ }
+ }
+out:
+ mutex_unlock(&dev->mode_config.mutex);
+ return ret;
+
+}
diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h
index 20b1ea06..64e7e519 100644
--- a/linux-core/drm_crtc.h
+++ b/linux-core/drm_crtc.h
@@ -649,6 +649,7 @@ extern int drm_mode_output_property_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_hotplug_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
-
+extern int drm_mode_replacefb(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
#endif /* __DRM_CRTC_H__ */
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index 649d4cae..82a9c19d 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -141,6 +141,8 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_HOTPLUG, drm_mode_hotplug_ioctl, DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_WAIT_HOTPLUG, drm_wait_hotplug, 0),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_REPLACEFB, drm_mode_replacefb, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
+
DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl,
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl,
diff --git a/shared-core/drm.h b/shared-core/drm.h
index c847b4ef..eb2033c7 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -1276,6 +1276,7 @@ struct drm_mode_hotplug {
#define DRM_IOCTL_MODE_HOTPLUG DRM_IOWR(0xAD, struct drm_mode_hotplug)
#define DRM_IOCTL_WAIT_HOTPLUG DRM_IOWR(0xAE, union drm_wait_hotplug)
+#define DRM_IOCTL_MODE_REPLACEFB DRM_IOWR(0xAF, struct drm_mode_fb_cmd)
/*@}*/
/**