diff options
author | Dave Airlie <airlied@redhat.com> | 2011-02-07 05:16:14 +0300 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-02-07 05:16:14 +0300 |
commit | ff72145badb834e8051719ea66e024784d000cb4 (patch) | |
tree | 39dc5fc512e3e0836713de9defb91ea8b4033aa2 /drivers/gpu/drm/i915 | |
parent | 1f692a14cbfbeb11f9a9c16f25c8ecb8ab50d3d5 (diff) | |
download | linux-ff72145badb834e8051719ea66e024784d000cb4.tar.xz |
drm: dumb scanout create/mmap for intel/radeon (v3)
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.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 103 |
3 files changed, 83 insertions, 30 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index cfb56d0ff367..17fde2f27418 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -700,6 +700,9 @@ 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, + .dumb_destroy = i915_gem_dumb_destroy, .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 a0149c619cdd..a78197d43ce6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1114,6 +1114,13 @@ void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, struct intel_ring_buffer *ring, u32 seqno); +int i915_gem_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); +int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev, + uint32_t handle, uint64_t *offset); +int i915_gem_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, + uint32_t handle); /** * Returns true if seq1 is later than seq2. */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cf4f74c7c6fb..bc7f06b8fbca 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -193,22 +193,20 @@ 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) +static int +i915_gem_create(struct drm_file *file, + struct drm_device *dev, + uint64_t size, + uint32_t *handle_p) { - struct drm_i915_gem_create *args = data; struct drm_i915_gem_object *obj; int ret; u32 handle; - args->size = roundup(args->size, PAGE_SIZE); + size = roundup(size, PAGE_SIZE); /* Allocate the new object */ - obj = i915_gem_alloc_object(dev, args->size); + obj = i915_gem_alloc_object(dev, size); if (obj == NULL) return -ENOMEM; @@ -224,10 +222,41 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, drm_gem_object_unreference(&obj->base); trace_i915_gem_object_create(obj); - args->handle = handle; + *handle_p = handle; return 0; } +int +i915_gem_dumb_create(struct drm_file *file, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + /* have to work out size/pitch and return them */ + args->pitch = ALIGN(args->width & ((args->bpp + 1) / 8), 64); + args->size = args->pitch * args->height; + return i915_gem_create(file, dev, + args->size, &args->handle); +} + +int i915_gem_dumb_destroy(struct drm_file *file, + struct drm_device *dev, + uint32_t handle) +{ + return drm_gem_handle_delete(file, handle); +} + +/** + * 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) +{ + struct drm_i915_gem_create *args = data; + return i915_gem_create(file, dev, + args->size, &args->handle); +} + static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj) { drm_i915_private_t *dev_priv = obj->base.dev->dev_private; @@ -1425,27 +1454,13 @@ i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj) return tile_height * obj->stride * 2; } -/** - * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing - * @dev: DRM device - * @data: GTT mapping ioctl data - * @file: 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) +i915_gem_mmap_gtt(struct drm_file *file, + struct drm_device *dev, + uint32_t handle, + uint64_t *offset) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_mmap_gtt *args = data; struct drm_i915_gem_object *obj; int ret; @@ -1456,7 +1471,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, if (ret) return ret; - obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle)); if (obj == NULL) { ret = -ENOENT; goto unlock; @@ -1479,7 +1494,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, goto out; } - args->offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT; + *offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT; out: drm_gem_object_unreference(&obj->base); @@ -1488,6 +1503,34 @@ unlock: return ret; } +/** + * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing + * @dev: DRM device + * @data: GTT mapping ioctl data + * @file: 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) +{ + struct drm_i915_gem_mmap_gtt *args = data; + + if (!(dev->driver->driver_features & DRIVER_GEM)) + return -ENODEV; + + return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset); +} + + static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, gfp_t gfpmask) |