drm_mode: initial replacefb implemenation
authorDave Airlie <airlied@linux.ie>
Thu, 8 May 2008 04:01:24 +0000 (14:01 +1000)
committerDave Airlie <airlied@linux.ie>
Thu, 8 May 2008 04:02:05 +0000 (14:02 +1000)
libdrm/xf86drmMode.c
libdrm/xf86drmMode.h
linux-core/drm_crtc.c
linux-core/drm_crtc.h
linux-core/drm_drv.c
shared-core/drm.h

index 605377d..ae15fd6 100644 (file)
@@ -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;
+}
index e5a6ee9..5171b59 100644 (file)
@@ -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
index 1e5195d..60255f5 100644 (file)
@@ -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;
+
+}
index 20b1ea0..64e7e51 100644 (file)
@@ -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__ */
 
index 649d4ca..82a9c19 100644 (file)
@@ -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,
index c847b4e..eb2033c 100644 (file)
@@ -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)
 /*@}*/
 
 /**