From: Dave Airlie <airl...@redhat.com>

This is just an idea that might or might not be a good idea,
it basically adds two ioctls to create a dumb and map a dumb buffer
suitable for scanout. The handle can be passed to the KMS ioctls to create
a framebuffer.

It looks to me like it would be useful in the following cases:
a) in development drivers - we can always provide a shadowfb fallback.
b) libkms users - we can clean up libkms a lot and avoid linking
to libdrm_*.
c) plymouth via libkms is a lot easier.

Userspace bits would be just calls + mmaps. We could probably
mark these handles somehow as not being suitable for acceleartion
so as top stop people who are dumber than dumb.
---
 drivers/gpu/drm/drm_crtc.c           |   23 +++++++++
 drivers/gpu/drm/drm_drv.c            |    4 +-
 drivers/gpu/drm/i915/i915_drv.c      |    2 +
 drivers/gpu/drm/i915/i915_drv.h      |    5 ++
 drivers/gpu/drm/i915/i915_gem.c      |   86 +++++++++++++++++++++-------------
 drivers/gpu/drm/radeon/radeon_drv.c  |    8 +++
 drivers/gpu/drm/radeon/radeon_gem.c  |   48 ++++++++++++++++--
 drivers/gpu/drm/radeon/radeon_mode.h |    2 +
 include/drm/drm.h                    |    3 +
 include/drm/drmP.h                   |    8 +++
 include/drm/drm_crtc.h               |    6 ++
 include/drm/drm_mode.h               |   20 ++++++++
 12 files changed, 176 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index d91fb8c..8d2e997 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2653,3 +2653,26 @@ out:
        mutex_unlock(&dev->mode_config.mutex);
        return ret;
 }
+
+int drm_mode_create_dumb_ioctl(struct drm_device *dev,
+                              void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_create_dumb *args = data;
+
+       if (!dev->driver->dumb_create)
+               return -ENOSYS;
+       
+       return dev->driver->dumb_create(file_priv, dev, args->size, 
&args->handle);
+}
+
+int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
+                            void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_map_dumb *args = data;
+
+       /* call driver ioctl to get mmap offset */
+       if (!dev->driver->dumb_map_offset)
+               return -ENOSYS;
+
+       return dev->driver->dumb_map_offset(file_priv, dev, args->handle, 
&args->offset);
+}
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index f3c58e2..4a3b007 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -146,7 +146,9 @@ static struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
        DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, 
DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
 };
 
 #define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 1b2e954..3a07392 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -526,6 +526,8 @@ static struct drm_driver driver = {
        .gem_init_object = i915_gem_init_object,
        .gem_free_object = i915_gem_free_object,
        .gem_vm_ops = &i915_gem_vm_ops,
+       .dumb_create = i915_gem_dumb_create,
+       .dumb_map_offset = i915_gem_mmap_gtt,
        .ioctls = i915_ioctls,
        .fops = {
                 .owner = THIS_MODULE,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 979439c..5bf054c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -930,6 +930,11 @@ void i915_gem_object_flush_write_domain(struct 
drm_gem_object *obj);
 
 void i915_gem_shrinker_init(void);
 void i915_gem_shrinker_exit(void);
+int i915_gem_dumb_create(struct drm_file *file_priv,
+                        struct drm_device *dev, uint64_t size,
+                        uint32_t *handle_p);
+int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev,
+                     uint32_t handle, uint64_t *offset);
 
 /* i915_gem_tiling.c */
 void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index fba37e9..1f1e8c6 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -107,23 +107,23 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void 
*data,
        return 0;
 }
 
-
 /**
  * Creates a new mm object and returns a handle to it.
  */
 int
-i915_gem_create_ioctl(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv)
+i915_gem_dumb_create(struct drm_file *file_priv,
+                    struct drm_device *dev, uint64_t size,
+                    uint32_t *handle_p)
+                     
 {
-       struct drm_i915_gem_create *args = data;
        struct drm_gem_object *obj;
        int ret;
        u32 handle;
 
-       args->size = roundup(args->size, PAGE_SIZE);
+       size = roundup(size, PAGE_SIZE);
 
        /* Allocate the new object */
-       obj = drm_gem_object_alloc(dev, args->size);
+       obj = drm_gem_object_alloc(dev, size);
        if (obj == NULL)
                return -ENOMEM;
 
@@ -133,10 +133,21 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
        if (ret)
                return ret;
 
-       args->handle = handle;
+       *handle_p = handle;
 
        return 0;
 }
+/**
+ * Creates a new mm object and returns a handle to it.
+ */
+int
+i915_gem_create_ioctl(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv)
+{
+       struct drm_i915_gem_create *args = data;
+       return i915_gem_dumb_create(file_priv, dev,
+                                   args->size, &args->handle);
+}
 
 static inline int
 fast_shmem_read(struct page **pages,
@@ -1371,35 +1382,18 @@ i915_gem_get_gtt_alignment(struct drm_gem_object *obj)
        return i;
 }
 
-/**
- * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
- * @dev: DRM device
- * @data: GTT mapping ioctl data
- * @file_priv: GEM object info
- *
- * Simply returns the fake offset to userspace so it can mmap it.
- * The mmap call will end up in drm_gem_mmap(), which will set things
- * up so we can get faults in the handler above.
- *
- * The fault handler will take care of binding the object into the GTT
- * (since it may have been evicted to make room for something), allocating
- * a fence register, and mapping the appropriate aperture address into
- * userspace.
- */
 int
-i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv)
+i915_gem_mmap_gtt(struct drm_file *file_priv,
+                 struct drm_device *dev,
+                 uint32_t handle,
+                 uint64_t *offset)
 {
-       struct drm_i915_gem_mmap_gtt *args = data;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_gem_object *obj;
        struct drm_i915_gem_object *obj_priv;
        int ret;
 
-       if (!(dev->driver->driver_features & DRIVER_GEM))
-               return -ENODEV;
-
-       obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+       obj = drm_gem_object_lookup(dev, file_priv, handle);
        if (obj == NULL)
                return -EBADF;
 
@@ -1424,7 +1418,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void 
*data,
                }
        }
 
-       args->offset = obj_priv->mmap_offset;
+       *offset = obj_priv->mmap_offset;
 
        /*
         * Pull it into the GTT so that we have a page list (makes the
@@ -1439,13 +1433,39 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void 
*data,
                }
                list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
        }
-
+       
        drm_gem_object_unreference(obj);
        mutex_unlock(&dev->struct_mutex);
-
        return 0;
 }
 
+/**
+ * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
+ * @dev: DRM device
+ * @data: GTT mapping ioctl data
+ * @file_priv: GEM object info
+ *
+ * Simply returns the fake offset to userspace so it can mmap it.
+ * The mmap call will end up in drm_gem_mmap(), which will set things
+ * up so we can get faults in the handler above.
+ *
+ * The fault handler will take care of binding the object into the GTT
+ * (since it may have been evicted to make room for something), allocating
+ * a fence register, and mapping the appropriate aperture address into
+ * userspace.
+ */
+int
+i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       struct drm_i915_gem_mmap_gtt *args = data;
+
+       if (!(dev->driver->driver_features & DRIVER_GEM))
+               return -ENODEV;
+
+       return i915_gem_mmap_gtt(file_priv, dev, args->handle, &args->offset);
+}
+
 void
 i915_gem_object_put_pages(struct drm_gem_object *obj)
 {
@@ -5165,3 +5185,5 @@ i915_gem_shrinker_exit(void)
 {
     unregister_shrinker(&shrinker);
 }
+
+
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index 6eec0ec..a714cfd 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -71,6 +71,12 @@ void radeon_gem_object_free(struct drm_gem_object *obj);
 extern struct drm_ioctl_desc radeon_ioctls_kms[];
 extern int radeon_max_kms_ioctl;
 int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
+int radeon_mode_dumb_mmap(struct drm_file *filp,
+                         struct drm_device *dev,
+                         uint32_t handle, uint64_t *offset_p);
+int radeon_mode_dumb_create(struct drm_file *file_priv,
+                           struct drm_device *dev, uint64_t size, uint32_t 
*handle_p);
+
 #if defined(CONFIG_DEBUG_FS)
 int radeon_debugfs_init(struct drm_minor *minor);
 void radeon_debugfs_cleanup(struct drm_minor *minor);
@@ -286,6 +292,8 @@ static struct drm_driver kms_driver = {
        .gem_init_object = radeon_gem_object_init,
        .gem_free_object = radeon_gem_object_free,
        .dma_ioctl = radeon_dma_ioctl_kms,
+       .dumb_create = radeon_mode_dumb_create,
+       .dumb_map_offset = radeon_mode_dumb_mmap,
        .fops = {
                 .owner = THIS_MODULE,
                 .open = drm_open,
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c 
b/drivers/gpu/drm/radeon/radeon_gem.c
index ef92d14..f16a4c7 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -234,23 +234,31 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, 
void *data,
        return r;
 }
 
-int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
-                         struct drm_file *filp)
+int radeon_mode_dumb_mmap(struct drm_file *filp,
+                         struct drm_device *dev,
+                         uint32_t handle, uint64_t *offset_p)
 {
-       struct drm_radeon_gem_mmap *args = data;
        struct drm_gem_object *gobj;
        struct radeon_bo *robj;
-
-       gobj = drm_gem_object_lookup(dev, filp, args->handle);
+       
+       gobj = drm_gem_object_lookup(dev, filp, handle);
        if (gobj == NULL) {
                return -EINVAL;
        }
        robj = gobj->driver_private;
-       args->addr_ptr = radeon_bo_mmap_offset(robj);
+       *offset_p = radeon_bo_mmap_offset(robj);
        drm_gem_object_unreference_unlocked(gobj);
        return 0;
 }
 
+int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *filp)
+{
+       struct drm_radeon_gem_mmap *args = data;
+
+       return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr);
+}
+
 int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *filp)
 {
@@ -343,3 +351,31 @@ out:
        drm_gem_object_unreference_unlocked(gobj);
        return r;
 }
+
+int radeon_mode_dumb_create(struct drm_file *file_priv,
+                           struct drm_device *dev, uint64_t size, uint32_t 
*handle_p)
+{
+       struct radeon_device *rdev = dev->dev_private;
+       struct drm_gem_object *gobj;
+       int r;
+       uint32_t handle;
+
+       size = ALIGN(size, PAGE_SIZE);
+
+       r = radeon_gem_object_create(rdev, size, 0,
+                                    RADEON_GEM_DOMAIN_VRAM,
+                                    false, ttm_bo_type_device,
+                                    &gobj);
+       if (r)
+               return -ENOMEM;
+
+       r = drm_gem_handle_create(file_priv, gobj, &handle);
+       if (r) {
+               drm_gem_object_unreference_unlocked(gobj);
+               return r;
+       }
+       drm_gem_object_handle_unreference_unlocked(gobj);
+       *handle_p = handle;
+       return 0;
+}
+
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h 
b/drivers/gpu/drm/radeon/radeon_mode.h
index 1702b82..832d056 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -575,4 +575,6 @@ void radeon_legacy_tv_adjust_pll2(struct drm_encoder 
*encoder,
 void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
                               struct drm_display_mode *mode,
                               struct drm_display_mode *adjusted_mode);
+
+
 #endif
diff --git a/include/drm/drm.h b/include/drm/drm.h
index e3f46e0..8a9bd6f 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -699,6 +699,9 @@ struct drm_gem_open {
 #define DRM_IOCTL_MODE_PAGE_FLIP       DRM_IOWR(0xB0, struct 
drm_mode_crtc_page_flip)
 #define DRM_IOCTL_MODE_DIRTYFB         DRM_IOWR(0xB1, struct 
drm_mode_fb_dirty_cmd)
 
+#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB0, struct drm_mode_create_dumb)
+#define DRM_IOCTL_MODE_MAP_DUMB    DRM_IOWR(0xB1, struct drm_mode_map_dumb)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x99.
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 4a3c4e4..d0933d0 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -806,6 +806,14 @@ struct drm_driver {
        /* vga arb irq handler */
        void (*vgaarb_irq)(struct drm_device *dev, bool state);
 
+       /* dumb alloc support */
+       int (*dumb_create)(struct drm_file *file_priv,
+                          struct drm_device *dev, uint64_t size,
+                          uint32_t *handle);
+       int (*dumb_map_offset)(struct drm_file *file_priv,
+                              struct drm_device *dev, uint32_t handle,
+                              uint64_t *offset);
+
        /* Driver private ops for this object */
        struct vm_operations_struct *gem_vm_ops;
 
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 1347524..4f8543c 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -803,4 +803,10 @@ extern int drm_add_modes_noedid(struct drm_connector 
*connector,
                                int hdisplay, int vdisplay);
 
 extern bool drm_edid_is_valid(struct edid *edid);
+
+extern int drm_mode_create_dumb_ioctl(struct drm_device *dev,
+                                     void *data, struct drm_file *file_priv);
+extern int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
+                                   void *data, struct drm_file *file_priv);
+
 #endif /* __DRM_CRTC_H__ */
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index c5ba163..c72d741 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -343,4 +343,24 @@ struct drm_mode_crtc_page_flip {
        __u64 user_data;
 };
 
+/* create a dumb scanout buffer */
+struct drm_mode_create_dumb {
+       uint64_t        size;
+       uint32_t        handle;
+       uint32_t        flags;
+};
+
+/* set up for mmap of a dumb scanout buffer */
+struct drm_mode_map_dumb {
+       /** Handle for the object being mapped. */
+       __u32 handle;
+       __u32 pad;
+       /**
+        * Fake offset to use for subsequent mmap call
+        *
+        * This is a fixed-size type for 32/64 compatibility.
+        */
+       __u64 offset;
+};
+
 #endif
-- 
1.6.5.2


------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to