summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel@tungstengraphics.com>2006-09-01 11:27:14 +0200
committerMichel Dänzer <michel@tungstengraphics.com>2006-09-28 15:41:36 +0200
commit89e323e4900af84cc33219ad24eb0b435a039d23 (patch)
tree6c55c148b5d5981d3e5eaf1d7d8d5afb51da0931
parent7f09f957d9a61ac107f8fd29128d7899a3e8a228 (diff)
Core vsync: Add flag DRM_VBLANK_NEXTONMISS.
When this flag is set and the target sequence is missed, wait for the next vertical blank instead of returning immediately.
-rw-r--r--libdrm/xf86drm.h1
-rw-r--r--linux-core/drm_irq.c16
-rw-r--r--shared-core/drm.h4
3 files changed, 14 insertions, 7 deletions
diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h
index cda570de..2ad70807 100644
--- a/libdrm/xf86drm.h
+++ b/libdrm/xf86drm.h
@@ -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;
diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c
index fef0e8d4..bd8a9c82 100644
--- a/linux-core/drm_irq.c
+++ b/linux-core/drm_irq.c
@@ -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);
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 614422bd..7f90a96d 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -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;