summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2009-09-11 13:27:35 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-10-29 17:14:09 -0700
commitb0b96636dbf93445dd532b09b21fa4fc5ce6bdc7 (patch)
tree651a1d6ea2aff02f9fe43c696401eca1d82fe434
parent0d7ad7e43ca212b1e9f16cd18f36493cab455e61 (diff)
Add support for vblank events
The kernel will now write data to the DRM fd for various event types if requested. Currently, the only supported event is a vblank event: it contains the vblank count for the event as well as a timestamp from when the event ocurred. Since the DRM fd is now pollable, it's easy to integrate into existing event loops.
-rw-r--r--libdrm/xf86drm.h19
-rw-r--r--libdrm/xf86drmMode.c43
-rw-r--r--shared-core/drm.h28
3 files changed, 90 insertions, 0 deletions
diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h
index c1d173c4..2cb9c9e9 100644
--- a/libdrm/xf86drm.h
+++ b/libdrm/xf86drm.h
@@ -271,6 +271,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_EVENT = 0x4000000, /**< Send event instead of blocking */
DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */
DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
@@ -667,4 +668,22 @@ extern void drmMsg(const char *format, ...);
extern int drmSetMaster(int fd);
extern int drmDropMaster(int fd);
+#define DRM_EVENT_CONTEXT_VERSION 1
+
+typedef struct _drmEventContext {
+
+ /* This struct is versioned so we can add more pointers if we
+ * add more events. */
+ int version;
+
+ void (*vblank_handler)(int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *user_data);
+
+} drmEventContext, *drmEventContextPtr;
+
+extern int drmHandleEvent(int fd, drmEventContextPtr evctx);
+
#endif
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c
index 88b4fe3a..6d85113a 100644
--- a/libdrm/xf86drmMode.c
+++ b/libdrm/xf86drmMode.c
@@ -46,6 +46,7 @@
#include <drm.h>
#include <string.h>
#include <dirent.h>
+#include <unistd.h>
#include <errno.h>
#define U642VOID(x) ((void *)(unsigned long)(x))
@@ -667,3 +668,45 @@ int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
return 0;
}
+
+int drmHandleEvent(int fd, drmEventContextPtr evctx)
+{
+ char buffer[1024];
+ int len, i;
+ struct drm_event *e;
+ struct drm_event_vblank *vblank;
+
+ /* The DRM read semantics guarantees that we always get only
+ * complete events. */
+
+ len = read(fd, buffer, sizeof buffer);
+ if (len == 0)
+ return 0;
+ if (len < sizeof *e)
+ return -1;
+
+ i = 0;
+ while (i < len) {
+ e = (struct drm_event *) &buffer[i];
+ switch (e->type) {
+ case DRM_EVENT_VBLANK:
+ if (evctx->version < 1 ||
+ evctx->vblank_handler == NULL)
+ break;
+ vblank = (struct drm_event_vblank *) e;
+ evctx->vblank_handler(fd,
+ vblank->sequence,
+ vblank->tv_sec,
+ vblank->tv_usec,
+ U642VOID (vblank->user_data));
+ break;
+
+ default:
+ break;
+ }
+ i += e->length;
+ }
+
+ return 0;
+}
+
diff --git a/shared-core/drm.h b/shared-core/drm.h
index d97844f8..089e184a 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -809,6 +809,34 @@ struct drm_gem_open {
#define DRM_COMMAND_BASE 0x40
#define DRM_COMMAND_END 0xA0
+/**
+ * Header for events written back to userspace on the drm fd. The
+ * type defines the type of event, the length specifies the total
+ * length of the event (including the header), and user_data is
+ * typically a 64 bit value passed with the ioctl that triggered the
+ * event. A read on the drm fd will always only return complete
+ * events, that is, if for example the read buffer is 100 bytes, and
+ * there are two 64 byte events pending, only one will be returned.
+ *
+ * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and
+ * up are chipset specific.
+ */
+struct drm_event {
+ uint32_t type;
+ uint32_t length;
+};
+
+#define DRM_EVENT_VBLANK 0x01
+
+struct drm_event_vblank {
+ struct drm_event base;
+ uint64_t user_data;
+ uint32_t tv_sec;
+ uint32_t tv_usec;
+ uint32_t sequence;
+ uint32_t reserved;
+};
+
/* typedef area */
#ifndef __KERNEL__
typedef struct drm_clip_rect drm_clip_rect_t;