Core vsync: Add flag DRM_VBLANK_NEXTONMISS.
authorMichel Dänzer <michel@tungstengraphics.com>
Fri, 1 Sep 2006 09:27:14 +0000 (11:27 +0200)
committerMichel Dänzer <michel@tungstengraphics.com>
Thu, 28 Sep 2006 13:41:36 +0000 (15:41 +0200)
When this flag is set and the target sequence is missed, wait for the next
vertical blank instead of returning immediately.

libdrm/xf86drm.h
linux-core/drm_irq.c
shared-core/drm.h

index cda570d..2ad7080 100644 (file)
@@ -252,6 +252,7 @@ typedef struct _drmTextureRegion {
 typedef enum {
     DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
     DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
+    DRM_VBLANK_NEXTONMISS = 0x10000000,        /**< If missed, wait for next vblank */
     DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
     DRM_VBLANK_SIGNAL   = 0x40000000   /* Send signal instead of blocking */
 } drmVBlankSeqType;
index fef0e8d..bd8a9c8 100644 (file)
@@ -249,8 +249,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
        drm_wait_vblank_t vblwait;
        struct timeval now;
        int ret = 0;
-       unsigned int flags;
-       atomic_t *seq;
+       unsigned int flags, seq;
 
        if ((!dev->irq) || (!dev->irq_enabled))
                return -EINVAL;
@@ -272,12 +271,12 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
                                    DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
                return -EINVAL;
 
-       seq = (flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2 :
-             &dev->vbl_received;
+       seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
+                         : &dev->vbl_received);
 
        switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) {
        case _DRM_VBLANK_RELATIVE:
-               vblwait.request.sequence += atomic_read(seq);
+               vblwait.request.sequence += seq;
                vblwait.request.type &= ~_DRM_VBLANK_RELATIVE;
        case _DRM_VBLANK_ABSOLUTE:
                break;
@@ -285,13 +284,18 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
                return -EINVAL;
        }
 
+       if ((flags & _DRM_VBLANK_NEXTONMISS) &&
+           (seq - vblwait.request.sequence) <= (1<<23)) {
+               vblwait.request.sequence = seq + 1;
+       }
+
        if (flags & _DRM_VBLANK_SIGNAL) {
                unsigned long irqflags;
                drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
                                      ? &dev->vbl_sigs2 : &dev->vbl_sigs;
                drm_vbl_sig_t *vbl_sig;
 
-               vblwait.reply.sequence = atomic_read(seq);
+               vblwait.reply.sequence = seq;
 
                spin_lock_irqsave(&dev->vbl_lock, irqflags);
 
index 614422b..7f90a96 100644 (file)
@@ -551,12 +551,14 @@ typedef struct drm_irq_busid {
 typedef enum {
        _DRM_VBLANK_ABSOLUTE = 0x0,     /**< Wait for specific vblank sequence number */
        _DRM_VBLANK_RELATIVE = 0x1,     /**< Wait for given number of vblanks */
+       _DRM_VBLANK_NEXTONMISS = 0x10000000,    /**< If missed, wait for next vblank */
        _DRM_VBLANK_SECONDARY = 0x20000000,     /**< Secondary display controller */
        _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
 } drm_vblank_seq_type_t;
 
 #define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
-#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY)
+#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \
+                               _DRM_VBLANK_NEXTONMISS)
 
 struct drm_wait_vblank_request {
        drm_vblank_seq_type_t type;