diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2009-09-11 14:33:34 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-11-17 19:02:47 -0500 |
commit | c9a9c5e02aedc1a2815877b0268f886d2640b771 (patch) | |
tree | 51f69f2ec6dcebb019cd6aa22b9e29ee48c397c1 /include/drm | |
parent | 799dd75b1a8380a967c929a4551895788c374b31 (diff) |
drm: Add async event synchronization for drmWaitVblank
This patch adds a new flag to the drmWaitVblank ioctl, which asks the drm
to return immediately and notify userspace when the specified vblank sequence
happens by sending an event back on the drm fd.
The event mechanism works with the other flags supported by the ioctls,
specifically, the vblank sequence can be specified relatively or absolutely,
and works for primary and seconday crtc.
The signal field of the vblank request is used to provide user data,
which will be sent back to user space in the vblank event.
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'include/drm')
-rw-r--r-- | include/drm/drm.h | 33 | ||||
-rw-r--r-- | include/drm/drmP.h | 26 |
2 files changed, 57 insertions, 2 deletions
diff --git a/include/drm/drm.h b/include/drm/drm.h index 7cb50bdde46d..fa6d9155873d 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h | |||
@@ -454,6 +454,7 @@ struct drm_irq_busid { | |||
454 | enum drm_vblank_seq_type { | 454 | enum drm_vblank_seq_type { |
455 | _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ | 455 | _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ |
456 | _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ | 456 | _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ |
457 | _DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */ | ||
457 | _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ | 458 | _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ |
458 | _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ | 459 | _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ |
459 | _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ | 460 | _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ |
@@ -461,8 +462,8 @@ enum drm_vblank_seq_type { | |||
461 | }; | 462 | }; |
462 | 463 | ||
463 | #define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) | 464 | #define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) |
464 | #define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \ | 465 | #define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \ |
465 | _DRM_VBLANK_NEXTONMISS) | 466 | _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS) |
466 | 467 | ||
467 | struct drm_wait_vblank_request { | 468 | struct drm_wait_vblank_request { |
468 | enum drm_vblank_seq_type type; | 469 | enum drm_vblank_seq_type type; |
@@ -698,6 +699,34 @@ struct drm_gem_open { | |||
698 | #define DRM_COMMAND_BASE 0x40 | 699 | #define DRM_COMMAND_BASE 0x40 |
699 | #define DRM_COMMAND_END 0xA0 | 700 | #define DRM_COMMAND_END 0xA0 |
700 | 701 | ||
702 | /** | ||
703 | * Header for events written back to userspace on the drm fd. The | ||
704 | * type defines the type of event, the length specifies the total | ||
705 | * length of the event (including the header), and user_data is | ||
706 | * typically a 64 bit value passed with the ioctl that triggered the | ||
707 | * event. A read on the drm fd will always only return complete | ||
708 | * events, that is, if for example the read buffer is 100 bytes, and | ||
709 | * there are two 64 byte events pending, only one will be returned. | ||
710 | * | ||
711 | * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and | ||
712 | * up are chipset specific. | ||
713 | */ | ||
714 | struct drm_event { | ||
715 | __u32 type; | ||
716 | __u32 length; | ||
717 | }; | ||
718 | |||
719 | #define DRM_EVENT_VBLANK 0x01 | ||
720 | |||
721 | struct drm_event_vblank { | ||
722 | struct drm_event base; | ||
723 | __u64 user_data; | ||
724 | __u32 tv_sec; | ||
725 | __u32 tv_usec; | ||
726 | __u32 sequence; | ||
727 | __u32 reserved; | ||
728 | }; | ||
729 | |||
701 | /* typedef area */ | 730 | /* typedef area */ |
702 | #ifndef __KERNEL__ | 731 | #ifndef __KERNEL__ |
703 | typedef struct drm_clip_rect drm_clip_rect_t; | 732 | typedef struct drm_clip_rect drm_clip_rect_t; |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index c8e64bbadbcf..b0b36838ab11 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -426,6 +426,14 @@ struct drm_buf_entry { | |||
426 | struct drm_freelist freelist; | 426 | struct drm_freelist freelist; |
427 | }; | 427 | }; |
428 | 428 | ||
429 | /* Event queued up for userspace to read */ | ||
430 | struct drm_pending_event { | ||
431 | struct drm_event *event; | ||
432 | struct list_head link; | ||
433 | struct drm_file *file_priv; | ||
434 | void (*destroy)(struct drm_pending_event *event); | ||
435 | }; | ||
436 | |||
429 | /** File private data */ | 437 | /** File private data */ |
430 | struct drm_file { | 438 | struct drm_file { |
431 | int authenticated; | 439 | int authenticated; |
@@ -449,6 +457,10 @@ struct drm_file { | |||
449 | struct drm_master *master; /* master this node is currently associated with | 457 | struct drm_master *master; /* master this node is currently associated with |
450 | N.B. not always minor->master */ | 458 | N.B. not always minor->master */ |
451 | struct list_head fbs; | 459 | struct list_head fbs; |
460 | |||
461 | wait_queue_head_t event_wait; | ||
462 | struct list_head event_list; | ||
463 | int event_space; | ||
452 | }; | 464 | }; |
453 | 465 | ||
454 | /** Wait queue */ | 466 | /** Wait queue */ |
@@ -900,6 +912,12 @@ struct drm_minor { | |||
900 | struct drm_mode_group mode_group; | 912 | struct drm_mode_group mode_group; |
901 | }; | 913 | }; |
902 | 914 | ||
915 | struct drm_pending_vblank_event { | ||
916 | struct drm_pending_event base; | ||
917 | int pipe; | ||
918 | struct drm_event_vblank event; | ||
919 | }; | ||
920 | |||
903 | /** | 921 | /** |
904 | * DRM device structure. This structure represent a complete card that | 922 | * DRM device structure. This structure represent a complete card that |
905 | * may contain multiple heads. | 923 | * may contain multiple heads. |
@@ -999,6 +1017,12 @@ struct drm_device { | |||
999 | 1017 | ||
1000 | u32 max_vblank_count; /**< size of vblank counter register */ | 1018 | u32 max_vblank_count; /**< size of vblank counter register */ |
1001 | 1019 | ||
1020 | /** | ||
1021 | * List of events | ||
1022 | */ | ||
1023 | struct list_head vblank_event_list; | ||
1024 | spinlock_t event_lock; | ||
1025 | |||
1002 | /*@} */ | 1026 | /*@} */ |
1003 | cycles_t ctx_start; | 1027 | cycles_t ctx_start; |
1004 | cycles_t lck_start; | 1028 | cycles_t lck_start; |
@@ -1135,6 +1159,8 @@ extern int drm_lastclose(struct drm_device *dev); | |||
1135 | extern int drm_open(struct inode *inode, struct file *filp); | 1159 | extern int drm_open(struct inode *inode, struct file *filp); |
1136 | extern int drm_stub_open(struct inode *inode, struct file *filp); | 1160 | extern int drm_stub_open(struct inode *inode, struct file *filp); |
1137 | extern int drm_fasync(int fd, struct file *filp, int on); | 1161 | extern int drm_fasync(int fd, struct file *filp, int on); |
1162 | extern ssize_t drm_read(struct file *filp, char __user *buffer, | ||
1163 | size_t count, loff_t *offset); | ||
1138 | extern int drm_release(struct inode *inode, struct file *filp); | 1164 | extern int drm_release(struct inode *inode, struct file *filp); |
1139 | 1165 | ||
1140 | /* Mapping support (drm_vm.h) */ | 1166 | /* Mapping support (drm_vm.h) */ |