diff options
-rw-r--r-- | .gitignore | 17 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | bsd-core/drmP.h | 26 | ||||
-rw-r--r-- | bsd-core/drm_dma.c | 4 | ||||
-rw-r--r-- | bsd-core/drm_drawable.c | 109 | ||||
-rw-r--r-- | bsd-core/drm_drv.c | 13 | ||||
-rw-r--r-- | bsd-core/drm_ioctl.c | 4 | ||||
-rw-r--r-- | bsd-core/drm_irq.c | 51 | ||||
-rw-r--r-- | bsd-core/drm_scatter.c | 4 | ||||
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | linux-core/drmP.h | 14 | ||||
-rw-r--r-- | shared-core/i915_dma.c | 14 | ||||
-rw-r--r-- | shared-core/i915_drv.h | 18 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 70 | ||||
-rw-r--r-- | tests/Makefile | 27 | ||||
-rw-r--r-- | tests/Makefile.am | 23 | ||||
-rw-r--r-- | tests/drmtest.c | 83 | ||||
-rw-r--r-- | tests/drmtest.h | 37 | ||||
-rw-r--r-- | tests/getclient.c | 60 | ||||
-rw-r--r-- | tests/getversion.c | 47 | ||||
-rw-r--r-- | tests/openclose.c | 37 | ||||
-rw-r--r-- | tests/updatedraw.c | 127 |
22 files changed, 698 insertions, 96 deletions
@@ -38,18 +38,26 @@ bsd-core/savage_drv.h bsd-core/savage_state.c bsd-core/sis_drm.h bsd-core/sis_drv.h +bsd-core/sis_ds.c +bsd-core/sis_ds.h +bsd-core/sis_mm.c bsd-core/tdfx_drv.h bsd-core/via_3d_reg.h bsd-core/via_dma.c bsd-core/via_drm.h bsd-core/via_drv.c bsd-core/via_drv.h +bsd-core/via_ds.c +bsd-core/via_ds.h bsd-core/via_irq.c bsd-core/via_map.c +bsd-core/via_mm.c +bsd-core/via_mm.h bsd-core/via_verifier.c bsd-core/via_verifier.h bsd-core/via_video.c -*~ +bsd-core/*/@ +bsd-core/*/machine *.flags *.ko *.ko.cmd @@ -75,6 +83,7 @@ config.log config.status config.sub configure +configure.lineno cscope.* depcomp device_if.h @@ -100,3 +109,9 @@ sis.kld stamp-h1 tdfx.kld via.kld +tests/dristat +tests/drmstat +tests/getclient +tests/getversion +tests/openclose +tests/updatedraw diff --git a/Makefile.am b/Makefile.am index 8c5dc702..5b1ae60a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,7 @@ # here too, but let's just do libdrm for now AUTOMAKE_OPTIONS = foreign -SUBDIRS = libdrm shared-core +SUBDIRS = libdrm shared-core tests pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA = libdrm.pc diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index 6e05b58f..fd8f4a27 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -59,6 +59,8 @@ typedef struct drm_file drm_file_t; #include <sys/bus.h> #include <sys/signalvar.h> #include <sys/poll.h> +#include <sys/tree.h> +#include <sys/taskqueue.h> #include <vm/vm.h> #include <vm/pmap.h> #include <vm/vm_extern.h> @@ -152,6 +154,7 @@ typedef struct drm_file drm_file_t; #define DRM_MEM_CTXBITMAP 17 #define DRM_MEM_STUB 18 #define DRM_MEM_SGLISTS 19 +#define DRM_MEM_DRAWABLE 20 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) @@ -184,10 +187,15 @@ MALLOC_DECLARE(M_DRM); #define DRM_CURPROC curthread #define DRM_STRUCTPROC struct thread #define DRM_SPINTYPE struct mtx -#define DRM_SPININIT(l,name) mtx_init(&l, name, NULL, MTX_DEF) -#define DRM_SPINUNINIT(l) mtx_destroy(&l) +#define DRM_SPININIT(l,name) mtx_init(l, name, NULL, MTX_DEF) +#define DRM_SPINUNINIT(l) mtx_destroy(l) #define DRM_SPINLOCK(l) mtx_lock(l) -#define DRM_SPINUNLOCK(u) mtx_unlock(u); +#define DRM_SPINUNLOCK(u) mtx_unlock(u) +#define DRM_SPINLOCK_IRQSAVE(l, irqflags) do { \ + mtx_lock(l); \ + (void)irqflags; \ +} while (0) +#define DRM_SPINUNLOCK_IRQRESTORE(u, irqflags) mtx_unlock(u) #define DRM_SPINLOCK_ASSERT(l) mtx_assert(l, MA_OWNED) #define DRM_CURRENTPID curthread->td_proc->p_pid #define DRM_LOCK() mtx_lock(&dev->dev_lock) @@ -732,6 +740,8 @@ struct drm_device { struct mtx irq_lock; /* protects irq condition checks */ struct mtx dev_lock; /* protects everything else */ #endif + DRM_SPINTYPE drw_lock; + /* Usage Counters */ int open_count; /* Outstanding files open */ int buf_use; /* Buffers in use -- cannot alloc */ @@ -780,6 +790,7 @@ struct drm_device { int last_context; /* Last current context */ int vbl_queue; /* vbl wait channel */ atomic_t vbl_received; + atomic_t vbl_received2; #ifdef __FreeBSD__ struct sigio *buf_sigio; /* Processes waiting for SIGIO */ @@ -796,6 +807,13 @@ struct drm_device { void *dev_private; unsigned int agp_buffer_token; drm_local_map_t *agp_buffer_map; + + struct unrhdr *drw_unrhdr; + /* RB tree of drawable infos */ + RB_HEAD(drawable_tree, bsd_drm_drawable_info) drw_head; + + struct task locked_task; + void (*locked_task_call)(drm_device_t *dev); }; extern int drm_debug_flag; @@ -958,6 +976,8 @@ int drm_getsareactx(DRM_IOCTL_ARGS); /* Drawable IOCTL support (drm_drawable.c) */ int drm_adddraw(DRM_IOCTL_ARGS); int drm_rmdraw(DRM_IOCTL_ARGS); +int drm_update_draw(DRM_IOCTL_ARGS); +struct drm_drawable_info *drm_get_drawable_info(drm_device_t *dev, int handle); /* Authentication IOCTL support (drm_auth.c) */ int drm_getmagic(DRM_IOCTL_ARGS); diff --git a/bsd-core/drm_dma.c b/bsd-core/drm_dma.c index 67b3fe2d..086a9fa2 100644 --- a/bsd-core/drm_dma.c +++ b/bsd-core/drm_dma.c @@ -40,7 +40,7 @@ int drm_dma_setup(drm_device_t *dev) if (dev->dma == NULL) return DRM_ERR(ENOMEM); - DRM_SPININIT(dev->dma_lock, "drmdma"); + DRM_SPININIT(&dev->dma_lock, "drmdma"); return 0; } @@ -80,7 +80,7 @@ void drm_dma_takedown(drm_device_t *dev) free(dma->pagelist, M_DRM); free(dev->dma, M_DRM); dev->dma = NULL; - DRM_SPINUNINIT(dev->dma_lock); + DRM_SPINUNINIT(&dev->dma_lock); } diff --git a/bsd-core/drm_drawable.c b/bsd-core/drm_drawable.c index 379e0aa7..ad25a6df 100644 --- a/bsd-core/drm_drawable.c +++ b/bsd-core/drm_drawable.c @@ -33,19 +33,120 @@ #include "drmP.h" +struct bsd_drm_drawable_info { + struct drm_drawable_info info; + int handle; + RB_ENTRY(bsd_drm_drawable_info) tree; +}; + +static int +drm_drawable_compare(struct bsd_drm_drawable_info *a, + struct bsd_drm_drawable_info *b) +{ + if (a->handle > b->handle) + return 1; + if (a->handle > b->handle) + return -1; + return 0; +} + +RB_GENERATE_STATIC(drawable_tree, bsd_drm_drawable_info, tree, + drm_drawable_compare); + +struct drm_drawable_info * +drm_get_drawable_info(drm_device_t *dev, int handle) +{ + struct bsd_drm_drawable_info find, *result; + + find.handle = handle; + result = RB_FIND(drawable_tree, &dev->drw_head, &find); + + return &result->info; +} + int drm_adddraw(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_draw_t draw; + struct bsd_drm_drawable_info *info; + + info = drm_calloc(1, sizeof(struct bsd_drm_drawable_info), + DRM_MEM_DRAWABLE); + if (info == NULL) + return ENOMEM; + + info->handle = alloc_unr(dev->drw_unrhdr); + DRM_SPINLOCK(&dev->drw_lock); + RB_INSERT(drawable_tree, &dev->drw_head, info); + draw.handle = info->handle; + DRM_SPINUNLOCK(&dev->drw_lock); - draw.handle = 0; /* NOOP */ DRM_DEBUG("%d\n", draw.handle); - - DRM_COPY_TO_USER_IOCTL( (drm_draw_t *)data, draw, sizeof(draw) ); + + DRM_COPY_TO_USER_IOCTL((drm_draw_t *)data, draw, sizeof(draw)); return 0; } int drm_rmdraw(DRM_IOCTL_ARGS) { - return 0; /* NOOP */ + DRM_DEVICE; + drm_draw_t *draw = (drm_draw_t *)data; + struct drm_drawable_info *info; + + DRM_SPINLOCK(&dev->drw_lock); + info = drm_get_drawable_info(dev, draw->handle); + if (info != NULL) { + RB_REMOVE(drawable_tree, &dev->drw_head, + (struct bsd_drm_drawable_info *)info); + DRM_SPINUNLOCK(&dev->drw_lock); + free_unr(dev->drw_unrhdr, draw->handle); + drm_free(info, sizeof(struct bsd_drm_drawable_info), + DRM_MEM_DRAWABLE); + } else { + DRM_SPINUNLOCK(&dev->drw_lock); + return EINVAL; + } +} + +int drm_update_draw(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + struct drm_drawable_info *info; + struct drm_update_draw *update = (struct drm_update_draw *)data; + int ret; + + info = drm_get_drawable_info(dev, update->handle); + if (info == NULL) + return EINVAL; + + switch (update->type) { + case DRM_DRAWABLE_CLIPRECTS: + DRM_SPINLOCK(&dev->drw_lock); + if (update->num != info->num_rects) { + drm_free(info->rects, + sizeof(*info->rects) * info->num_rects, + DRM_MEM_DRAWABLE); + info->rects = NULL; + info->num_rects = 0; + } + if (update->num == 0) { + DRM_SPINUNLOCK(&dev->drw_lock); + return 0; + } + if (info->rects == NULL) { + info->rects = drm_alloc(sizeof(*info->rects) * + update->num, DRM_MEM_DRAWABLE); + if (info->rects == NULL) + return ENOMEM; + info->num_rects = update->num; + } + /* For some reason the pointer arg is unsigned long long. */ + ret = copyin((void *)(intptr_t)update->data, info->rects, + sizeof(*info->rects) * info->num_rects); + DRM_SPINUNLOCK(&dev->drw_lock); + return ret; + default: + return EINVAL; + } } diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c index 069774c1..75866b1b 100644 --- a/bsd-core/drm_drv.c +++ b/bsd-core/drm_drv.c @@ -31,6 +31,7 @@ * */ +#include <sys/limits.h> #include "drmP.h" #include "drm.h" #include "drm_sarea.h" @@ -121,6 +122,7 @@ static drm_ioctl_desc_t drm_ioctls[256] = { [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { drm_wait_vblank, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = { drm_update_draw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, }; #ifdef __FreeBSD__ @@ -198,6 +200,7 @@ int drm_attach(device_t nbdev, drm_pci_id_list_t *idlist) "dri/card%d", unit); #if __FreeBSD_version >= 500000 mtx_init(&dev->dev_lock, "drm device", NULL, MTX_DEF); + mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF); #endif id_entry = drm_find_description(pci_get_vendor(dev->device), @@ -556,7 +559,13 @@ static int drm_load(drm_device_t *dev) DRM_ERROR("Cannot allocate memory for context bitmap.\n"); goto error; } - + + dev->drw_unrhdr = new_unrhdr(1, INT_MAX, NULL); + if (dev->drw_unrhdr == NULL) { + DRM_ERROR("Couldn't allocate drawable number allocator\n"); + goto error; + } + DRM_INFO("Initialized %s %d.%d.%d %s\n", dev->driver.name, dev->driver.major, @@ -628,6 +637,8 @@ static void drm_unload(drm_device_t *dev) if (dev->driver.unload != NULL) dev->driver.unload(dev); + delete_unrhdr(dev->drw_unrhdr); + drm_mem_uninit(); #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 mtx_destroy(&dev->dev_lock); diff --git a/bsd-core/drm_ioctl.c b/bsd-core/drm_ioctl.c index e22faa83..b5b5cf58 100644 --- a/bsd-core/drm_ioctl.c +++ b/bsd-core/drm_ioctl.c @@ -213,9 +213,7 @@ int drm_getclient(DRM_IOCTL_ARGS) } DRM_UNLOCK(); - DRM_COPY_TO_USER_IOCTL( (drm_client_t *)data, client, sizeof(client) ); - - return 0; + return EINVAL; } int drm_getstats(DRM_IOCTL_ARGS) diff --git a/bsd-core/drm_irq.c b/bsd-core/drm_irq.c index f7da5ed7..2a69e014 100644 --- a/bsd-core/drm_irq.c +++ b/bsd-core/drm_irq.c @@ -31,6 +31,8 @@ #include "drmP.h" #include "drm.h" +static void drm_locked_task(void *context, int pending __unused); + int drm_irq_by_busid(DRM_IOCTL_ARGS) { DRM_DEVICE; @@ -87,7 +89,7 @@ int drm_irq_install(drm_device_t *dev) dev->context_flag = 0; - DRM_SPININIT(dev->irq_lock, "DRM IRQ lock"); + DRM_SPININIT(&dev->irq_lock, "DRM IRQ lock"); /* Before installing handler */ dev->driver.irq_preinstall(dev); @@ -131,6 +133,7 @@ int drm_irq_install(drm_device_t *dev) dev->driver.irq_postinstall(dev); DRM_UNLOCK(); + TASK_INIT(&dev->locked_task, 0, drm_locked_task, dev); return 0; err: DRM_LOCK(); @@ -142,7 +145,7 @@ err: dev->irqrid = 0; } #endif - DRM_SPINUNINIT(dev->irq_lock); + DRM_SPINUNINIT(&dev->irq_lock); DRM_UNLOCK(); return retcode; } @@ -174,7 +177,7 @@ int drm_irq_uninstall(drm_device_t *dev) #elif defined(__NetBSD__) || defined(__OpenBSD__) pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh); #endif - DRM_SPINUNINIT(dev->irq_lock); + DRM_SPINUNINIT(&dev->irq_lock); return 0; } @@ -291,3 +294,45 @@ void drm_vbl_send_signals( drm_device_t *dev ) } } #endif + +static void drm_locked_task(void *context, int pending __unused) +{ + drm_device_t *dev = context; + + DRM_LOCK(); + for (;;) { + int ret; + + if (drm_lock_take(&dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) + { + dev->lock.filp = (void *)(uintptr_t)DRM_CURRENTPID; + dev->lock.lock_time = jiffies; + atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); + break; /* Got lock */ + } + + /* Contention */ +#if defined(__FreeBSD__) && __FreeBSD_version > 500000 + ret = msleep((void *)&dev->lock.lock_queue, &dev->dev_lock, + PZERO | PCATCH, "drmlk2", 0); +#else + ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH, + "drmlk2", 0); +#endif + if (ret != 0) + return; + } + DRM_UNLOCK(); + + dev->locked_task_call(dev); + + drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); +} + +void +drm_locked_tasklet(drm_device_t *dev, void (*tasklet)(drm_device_t *dev)) +{ + dev->locked_task_call = tasklet; + taskqueue_enqueue(taskqueue_swi, &dev->locked_task); +} diff --git a/bsd-core/drm_scatter.c b/bsd-core/drm_scatter.c index 46222f18..3c0be4a0 100644 --- a/bsd-core/drm_scatter.c +++ b/bsd-core/drm_scatter.c @@ -44,6 +44,7 @@ int drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request) { drm_sg_mem_t *entry; unsigned long pages; + int i; if ( dev->sg ) return EINVAL; @@ -52,7 +53,7 @@ int drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request) if ( !entry ) return ENOMEM; - pages = round_page(request.size) / PAGE_SIZE; + pages = round_page(request->size) / PAGE_SIZE; DRM_DEBUG( "sg size=%ld pages=%ld\n", request->size, pages ); entry->pages = pages; @@ -89,6 +90,7 @@ int drm_sg_alloc(drm_device_t * dev, drm_scatter_gather_t * request) dev->sg = entry; DRM_UNLOCK(); + return 0; } int drm_sg_alloc_ioctl(DRM_IOCTL_ARGS) diff --git a/configure.ac b/configure.ac index 94c47bd1..78203343 100644 --- a/configure.ac +++ b/configure.ac @@ -35,4 +35,9 @@ AC_SYS_LARGEFILE pkgconfigdir=${libdir}/pkgconfig AC_SUBST(pkgconfigdir) -AC_OUTPUT([Makefile libdrm/Makefile shared-core/Makefile libdrm.pc]) +AC_OUTPUT([ + Makefile + libdrm/Makefile + shared-core/Makefile + tests/Makefile + libdrm.pc]) diff --git a/linux-core/drmP.h b/linux-core/drmP.h index c5dfe6bf..575e6255 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -1260,5 +1260,19 @@ static inline void drm_ctl_free(void *pt, size_t size, int area) /*@}*/ +/** Type for the OS's non-sleepable mutex lock */ +#define DRM_SPINTYPE spinlock_t +/** + * Initialize the lock for use. name is an optional string describing the + * lock + */ +#define DRM_SPININIT(l,name) spin_lock_init(l); +#define DRM_SPINUNINIT(l) +#define DRM_SPINLOCK(l) spin_lock(l); +#define DRM_SPINUNLOCK(u) spin_unlock(l); +#define DRM_SPINLOCK_IRQSAVE(l, flags) spin_lock_irqflags(l, _flags); +#define DRM_SPINUNLOCK_IRQRESTORE(u, flags) spin_unlock_irqrestore(l, _flags); +#define DRM_SPINLOCK_ASSERT(l) do {} while (0) + #endif /* __KERNEL__ */ #endif diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index c3a41bd5..5fb9fcff 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -855,12 +855,14 @@ static int mmio_table_size = sizeof(mmio_table)/sizeof(drm_i915_mmio_entry_t); static int i915_mmio(DRM_IOCTL_ARGS) { - char buf[32]; + uint32_t buf[8]; DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_mmio_entry_t *e; drm_i915_mmio_t mmio; void __iomem *base; + int i; + if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); @@ -878,7 +880,8 @@ static int i915_mmio(DRM_IOCTL_ARGS) case I915_MMIO_READ: if (!(e->flag & I915_MMIO_MAY_READ)) return DRM_ERR(EINVAL); - memcpy_fromio(buf, base, e->size); + for (i = 0; i < e->size / 4; i++) + buf[i] = I915_READ(e->offset + i * 4); if (DRM_COPY_TO_USER(mmio.data, buf, e->size)) { DRM_ERROR("DRM_COPY_TO_USER failed\n"); return DRM_ERR(EFAULT); @@ -892,7 +895,8 @@ static int i915_mmio(DRM_IOCTL_ARGS) DRM_ERROR("DRM_COPY_TO_USER failed\n"); return DRM_ERR(EFAULT); } - memcpy_toio(base, buf, e->size); + for (i = 0; i < e->size / 4; i++) + I915_WRITE(e->offset + i * 4, buf[i]); break; } return 0; @@ -910,11 +914,11 @@ static int i915_set_status_page(DRM_IOCTL_ARGS) } DRM_COPY_FROM_USER_IOCTL(hws, (drm_i915_hws_addr_t __user *) data, sizeof(hws)); - printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws.addr); + DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws.addr); dev_priv->status_gfx_addr = hws.addr & (0x1ffff<<12); - dev_priv->hws_map.offset = dev->agp->agp_info.aper_base + hws.addr; + dev_priv->hws_map.offset = dev->agp->base + hws.addr; dev_priv->hws_map.size = 4*1024; dev_priv->hws_map.type = 0; dev_priv->hws_map.flags = 0; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index ee2b474b..1a2220a5 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -39,6 +39,11 @@ #define DRIVER_DESC "Intel Graphics" #define DRIVER_DATE "20070209" +#if defined(__linux__) +#define I915_HAVE_FENCE +#define I915_HAVE_BUFFER +#endif + /* Interface history: * * 1.1: Original. @@ -52,13 +57,12 @@ * 1.9: Usable page flipping and triple buffering */ #define DRIVER_MAJOR 1 +#if defined(I915_HAVE_FENCE) && defined(I915_HAVE_BUFFER) #define DRIVER_MINOR 9 -#define DRIVER_PATCHLEVEL 0 - -#if defined(__linux__) -#define I915_HAVE_FENCE -#define I915_HAVE_BUFFER +#else +#define DRIVER_MINOR 6 #endif +#define DRIVER_PATCHLEVEL 0 typedef struct _drm_i915_ring_buffer { int tail_mask; @@ -114,7 +118,7 @@ typedef struct drm_i915_private { struct mem_block *agp_heap; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; int vblank_pipe; - spinlock_t user_irq_lock; + DRM_SPINTYPE user_irq_lock; int user_irq_refcount; int fence_irq_on; uint32_t irq_enable_reg; @@ -129,7 +133,7 @@ typedef struct drm_i915_private { #ifdef I915_HAVE_BUFFER void *agp_iomap; #endif - spinlock_t swaps_lock; + DRM_SPINTYPE swaps_lock; drm_i915_vbl_swap_t vbl_swaps; unsigned int swaps_pending; } drm_i915_private_t; diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 17cccac3..698ecced 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -51,6 +51,8 @@ i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw, u16 x1, y1, x2, y2; int pf_pipes = 1 << pipe; + DRM_SPINLOCK_ASSERT(&dev->drw_lock); + /* If the window is visible on the other pipe, we have to flip on that * pipe as well. */ @@ -90,7 +92,6 @@ i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw, static void i915_vblank_tasklet(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long irqflags; struct list_head *list, *tmp, hits, *hit; int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages; unsigned counter[2] = { atomic_read(&dev->vbl_received), @@ -112,7 +113,12 @@ static void i915_vblank_tasklet(struct drm_device *dev) nhits = nrects = 0; - spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); + /* No irqsave/restore necessary. This tasklet may be run in an + * interrupt context or normal context, but we don't have to worry + * about getting interrupted by something acquiring the lock, because + * we are the interrupt context thing that acquires the lock. + */ + DRM_SPINLOCK(&dev_priv->swaps_lock); /* Find buffer swaps scheduled for this vertical blank */ list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { @@ -125,15 +131,15 @@ static void i915_vblank_tasklet(struct drm_device *dev) list_del(list); dev_priv->swaps_pending--; - spin_unlock(&dev_priv->swaps_lock); - spin_lock(&dev->drw_lock); + DRM_SPINUNLOCK(&dev_priv->swaps_lock); + DRM_SPINLOCK(&dev->drw_lock); drw = drm_get_drawable_info(dev, vbl_swap->drw_id); if (!drw) { - spin_unlock(&dev->drw_lock); + DRM_SPINUNLOCK(&dev->drw_lock); drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); - spin_lock(&dev_priv->swaps_lock); + DRM_SPINLOCK(&dev_priv->swaps_lock); continue; } @@ -150,7 +156,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) } } - spin_unlock(&dev->drw_lock); + DRM_SPINUNLOCK(&dev->drw_lock); /* List of hits was empty, or we reached the end of it */ if (hit == &hits) @@ -158,16 +164,15 @@ static void i915_vblank_tasklet(struct drm_device *dev) nhits++; - spin_lock(&dev_priv->swaps_lock); + DRM_SPINLOCK(&dev_priv->swaps_lock); } + DRM_SPINUNLOCK(&dev->drw_lock); + if (nhits == 0) { - spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); return; } - spin_unlock(&dev_priv->swaps_lock); - i915_kernel_lost_context(dev); upper[0] = upper[1] = 0; @@ -181,7 +186,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) offsets[2] = sarea_priv->third_offset; num_pages = sarea_priv->third_handle ? 3 : 2; - spin_lock(&dev->drw_lock); + DRM_SPINLOCK(&dev->drw_lock); /* Emit blits for buffer swaps, partitioning both outputs into as many * slices as there are buffer swaps scheduled in order to avoid tearing @@ -263,7 +268,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) } } - spin_unlock_irqrestore(&dev->drw_lock, irqflags); + DRM_SPINUNLOCK(&dev->drw_lock); list_for_each_safe(hit, tmp, &hits) { drm_i915_vbl_swap_t *swap_hit = @@ -363,23 +368,23 @@ int i915_emit_irq(struct drm_device * dev) void i915_user_irq_on(drm_i915_private_t *dev_priv) { - spin_lock(&dev_priv->user_irq_lock); + DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){ dev_priv->irq_enable_reg |= USER_INT_FLAG; I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); } - spin_unlock(&dev_priv->user_irq_lock); + DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } void i915_user_irq_off(drm_i915_private_t *dev_priv) { - spin_lock(&dev_priv->user_irq_lock); + DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { // dev_priv->irq_enable_reg &= ~USER_INT_FLAG; // I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); } - spin_unlock(&dev_priv->user_irq_lock); + DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } @@ -598,16 +603,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) return DRM_ERR(EINVAL); } - spin_lock_irqsave(&dev->drw_lock, irqflags); - - if (!drm_get_drawable_info(dev, swap.drawable)) { - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - DRM_DEBUG("Invalid drawable ID %d\n", swap.drawable); - return DRM_ERR(EINVAL); - } - - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received); if (seqtype == _DRM_VBLANK_RELATIVE) @@ -630,12 +625,13 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - spin_lock_irqsave(&dev->drw_lock, irqflags); + DRM_SPINLOCK_IRQSAVE(&dev->drw_lock, irqflags); drw = drm_get_drawable_info(dev, swap.drawable); if (!drw) { - spin_unlock_irqrestore(&dev->drw_lock, irqflags); + DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, + irqflags); DRM_DEBUG("Invalid drawable ID %d\n", swap.drawable); return DRM_ERR(EINVAL); @@ -643,13 +639,13 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) i915_dispatch_vsync_flip(dev, drw, pipe); - spin_unlock_irqrestore(&dev->drw_lock, irqflags); + DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags); return 0; } } - spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); + DRM_SPINLOCK_IRQSAVE(&dev_priv->swaps_lock, irqflags); list_for_each(list, &dev_priv->vbl_swaps.head) { vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); @@ -658,13 +654,13 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) vbl_swap->pipe == pipe && vbl_swap->sequence == swap.sequence) { vbl_swap->flip = (swap.seqtype & _DRM_VBLANK_FLIP); - spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); + DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->swaps_lock, irqflags); DRM_DEBUG("Already scheduled\n"); return 0; } } - spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); + DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->swaps_lock, irqflags); if (dev_priv->swaps_pending >= 100) { DRM_DEBUG("Too many swaps queued\n"); @@ -688,12 +684,12 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) if (vbl_swap->flip) swap.sequence++; - spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); + DRM_SPINLOCK_IRQSAVE(&dev_priv->swaps_lock, irqflags); list_add_tail((struct list_head *)vbl_swap, &dev_priv->vbl_swaps.head); dev_priv->swaps_pending++; - spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); + DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->swaps_lock, irqflags); DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_swap_t __user *) data, swap, sizeof(swap)); @@ -716,11 +712,11 @@ void i915_driver_irq_postinstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - spin_lock_init(&dev_priv->swaps_lock); + DRM_SPININIT(&dev_priv->swaps_lock, "swap"); INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); dev_priv->swaps_pending = 0; - spin_lock_init(&dev_priv->user_irq_lock); + DRM_SPININIT(&dev_priv->user_irq_lock, "userirq"); dev_priv->user_irq_refcount = 0; i915_enable_interrupt(dev); diff --git a/tests/Makefile b/tests/Makefile deleted file mode 100644 index b406e0ad..00000000 --- a/tests/Makefile +++ /dev/null @@ -1,27 +0,0 @@ - -# These definitions are for handling dependencies in the out of kernel build. - -PROGS = dristat drmstat - -CLEANFILES = *.o *.ko $(PROGS) .depend .*.flags .*.d - -# Build test utilities - -PRGCFLAGS = $(CFLAGS) -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \ - -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \ - -I. -I../libdrm -I../shared-core - -DRMSTATLIBS = -L../libdrm -ldrm - - -programs: $(PROGS) - -dristat: dristat.c - $(CC) $(PRGCFLAGS) $< -o $@ - -drmstat: drmstat.c - $(CC) $(PRGCFLAGS) $< -o $@ $(DRMSTATLIBS) - -clean: - rm -f $(CLEANFILES) - diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 00000000..3b97fb79 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,23 @@ +AM_CFLAGS = \ + -I $(top_srcdir)/shared-core + +noinst_PROGRAMS = \ + dristat \ + drmstat + +EXTRA_LTLIBRARIES = libdrmtest.la +libdrmtest_la_SOURCES = \ + drmtest.c \ + drmtest.h +libdrmtest_la_LIBADD = \ + $(top_builddir)/libdrm/libdrm.la + +LDADD = libdrmtest.la + +TESTS = openclose \ + getversion \ + getclient \ + updatedraw + +EXTRA_PROGRAMS = $(TESTS) +CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LTLIBRARIES)
\ No newline at end of file diff --git a/tests/drmtest.c b/tests/drmtest.c new file mode 100644 index 00000000..cae99a0c --- /dev/null +++ b/tests/drmtest.c @@ -0,0 +1,83 @@ +/* + * Copyright © 2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#include <fcntl.h> +#include "drmtest.h" + +/** Open the first DRM device we can find, searching up to 16 device nodes */ +int drm_open_any(void) +{ + char name[20]; + int i, fd; + + for (i = 0; i < 16; i++) { + sprintf(name, "/dev/dri/card%d", i); + fd = open(name, O_RDWR); + if (fd != -1) + return fd; + } + abort(); +} + + +/** + * Open the first DRM device we can find where we end up being the master. + */ +int drm_open_any_master(void) +{ + char name[20]; + int i, fd; + + for (i = 0; i < 16; i++) { + drm_client_t client; + int ret; + + sprintf(name, "/dev/dri/card%d", i); + fd = open(name, O_RDWR); + if (fd == -1) + continue; + + /* Check that we're the only opener and authed. */ + client.idx = 0; + ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client); + assert (ret == 0); + if (!client.auth) { + close(fd); + continue; + } + client.idx = 1; + ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client); + if (ret != -1 || errno != EINVAL) { + close(fd); + continue; + } + return fd; + } + fprintf(stderr, "Couldn't find an un-controlled DRM device\n"); + abort(); +} + diff --git a/tests/drmtest.h b/tests/drmtest.h new file mode 100644 index 00000000..afa0df4a --- /dev/null +++ b/tests/drmtest.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <errno.h> + +#include "xf86drm.h" + +int drm_open_any(void); +int drm_open_any_master(void); diff --git a/tests/getclient.c b/tests/getclient.c new file mode 100644 index 00000000..349c16ec --- /dev/null +++ b/tests/getclient.c @@ -0,0 +1,60 @@ +/* + * Copyright © 2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#include <limits.h> +#include "drmtest.h" + +/** + * Checks DRM_IOCTL_GET_CLIENT. + */ +int main(int argc, char **argv) +{ + int fd, ret; + drm_client_t client; + + fd = drm_open_any(); + + /* Look for client index 0. This should exist whether we're operating + * on an otherwise unused drm device, or the X Server is running on + * the device. + */ + client.idx = 0; + ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client); + assert(ret == 0); + + /* Look for some absurd client index and make sure it's invalid. + * The DRM drivers currently always return data, so the user has + * no real way to detect when the list has terminated. That's bad, + * and this test is XFAIL as a result. + */ + client.idx = 0x7fffffff; + ret = ioctl(fd, DRM_IOCTL_GET_CLIENT, &client); + assert(ret == -1 && errno == EINVAL); + + close(fd); + return 0; +} diff --git a/tests/getversion.c b/tests/getversion.c new file mode 100644 index 00000000..3de90de6 --- /dev/null +++ b/tests/getversion.c @@ -0,0 +1,47 @@ +/* + * Copyright © 2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#include "drmtest.h" + +/** + * Checks DRM_IOCTL_GET_VERSION and libdrm's drmGetVersion() interface to it. + */ +int main(int argc, char **argv) +{ + int fd; + drmVersionPtr v; + + fd = drm_open_any(); + v = drmGetVersion(fd); + assert(strlen(v->name) != 0); + assert(strlen(v->date) != 0); + assert(strlen(v->desc) != 0); + assert(v->version_major >= 1); + drmFree(v); + close(fd); + return 0; +} diff --git a/tests/openclose.c b/tests/openclose.c new file mode 100644 index 00000000..946a4459 --- /dev/null +++ b/tests/openclose.c @@ -0,0 +1,37 @@ +/* + * Copyright © 2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#include "drmtest.h" + +int main(int argc, char **argv) +{ + int fd; + + fd = drm_open_any(); + close(fd); + return 0; +} diff --git a/tests/updatedraw.c b/tests/updatedraw.c new file mode 100644 index 00000000..1186783a --- /dev/null +++ b/tests/updatedraw.c @@ -0,0 +1,127 @@ +/* + * Copyright © 2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#include "drmtest.h" + +static void +set_draw_cliprects_empty(int fd, int drawable) +{ + int ret; + struct drm_update_draw update; + + update.handle = drawable; + update.type = DRM_DRAWABLE_CLIPRECTS; + update.num = 0; + update.data = 0; + + ret = ioctl(fd, DRM_IOCTL_UPDATE_DRAW, &update); + assert(ret == 0); +} + +static void +set_draw_cliprects_empty_fail(int fd, int drawable) +{ + int ret; + struct drm_update_draw update; + + update.handle = drawable; + update.type = DRM_DRAWABLE_CLIPRECTS; + update.num = 0; + update.data = 0; + + ret = ioctl(fd, DRM_IOCTL_UPDATE_DRAW, &update); + assert(ret == -1 && errno == EINVAL); +} + +static void +set_draw_cliprects_2(int fd, int drawable) +{ + int ret; + struct drm_update_draw update; + drm_clip_rect_t rects[2]; + + rects[0].x1 = 0; + rects[0].y1 = 0; + rects[0].x2 = 10; + rects[0].y2 = 10; + + rects[1].x1 = 10; + rects[1].y1 = 10; + rects[1].x2 = 20; + rects[1].y2 = 20; + + update.handle = drawable; + update.type = DRM_DRAWABLE_CLIPRECTS; + update.num = 2; + update.data = (unsigned long long)(uintptr_t)&rects; + + ret = ioctl(fd, DRM_IOCTL_UPDATE_DRAW, &update); + assert(ret == 0); +} + +/** + * Tests drawable management: adding, removing, and updating the cliprects of + * drawables. + */ +int main(int argc, char **argv) +{ + drm_draw_t drawarg; + int fd, ret, drawable; + + fd = drm_open_any_master(); + + /* Create a drawable. + * IOCTL_ADD_DRAW is RDWR, though it should really just be RD + */ + drawarg.handle = 0; + ret = ioctl(fd, DRM_IOCTL_ADD_DRAW, &drawarg); + assert(ret == 0); + drawable = drawarg.handle; + + /* Do a series of cliprect updates */ + set_draw_cliprects_empty(fd, drawable); + set_draw_cliprects_2(fd, drawable); + set_draw_cliprects_empty(fd, drawable); + + /* Remove our drawable */ + drawarg.handle = drawable; + ret = ioctl(fd, DRM_IOCTL_RM_DRAW, &drawarg); + assert(ret == 0); + drawable = drawarg.handle; + + /* Check that removing an unknown drawable returns error */ + drawarg.handle = 0x7fffffff; + ret = ioctl(fd, DRM_IOCTL_RM_DRAW, &drawarg); + assert(ret == -1 && errno == EINVAL); + drawable = drawarg.handle; + + /* Attempt to set cliprects on a nonexistent drawable */ + set_draw_cliprects_empty_fail(fd, drawable); + + close(fd); + return 0; +} |