diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h index c1d173c..67bea37 100644 --- a/libdrm/xf86drm.h +++ b/libdrm/xf86drm.h @@ -667,4 +667,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 (*page_flip_handler)(int fd, + unsigned int frame, + 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 ea11207..f601a00 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -664,3 +664,56 @@ int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, return 0; } + +int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, void *user_data) +{ + struct drm_mode_page_flip flip; + + flip.fb_id = fb_id; + flip.crtc_id = crtc_id; + flip.user_data = VOID2U64(user_data); + flip.flags = 0; + + return drmIoctl(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); +} + +int drmHandleEvent(int fd, drmEventContextPtr evctx) +{ + char buffer[1024]; + int len, i; + struct drm_event *e; + struct drm_event_page_flip *page_flip; + + /* 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_MODE_PAGE_FLIP: + if (evctx->version < 1 || + evctx->page_flip_handler == NULL) + break; + page_flip = (struct drm_event_page_flip *) e; + evctx->page_flip_handler(fd, + page_flip->frame, + page_flip->tv_sec, + page_flip->tv_usec, + U642VOID (page_flip->user_data)); + break; + + default: + break; + } + i += e->length; + } + + return 0; +} diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h index 62304bb..fe64707 100644 --- a/libdrm/xf86drmMode.h +++ b/libdrm/xf86drmMode.h @@ -259,8 +259,6 @@ typedef struct _drmModeConnector { uint32_t *encoders; /**< List of encoder ids */ } drmModeConnector, *drmModeConnectorPtr; - - extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr ); extern void drmModeFreeResources( drmModeResPtr ptr ); extern void drmModeFreeFB( drmModeFBPtr ptr ); @@ -362,3 +360,4 @@ extern int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue); extern int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue); +extern int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, void *user_data); diff --git a/shared-core/drm.h b/shared-core/drm.h index 97fab9a..8b504cb 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -1113,7 +1113,7 @@ struct drm_gem_open { #define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) #define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) #define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, uint32_t) -#define DRM_IOCTL_MODE_REPLACEFB DRM_IOWR(0xB0, struct drm_mode_fb_cmd) +#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOW( 0xB0, struct drm_mode_page_flip) /*@}*/ @@ -1128,6 +1128,30 @@ 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. + */ +struct drm_event { + uint32_t type; + uint32_t length; +}; + +#define DRM_EVENT_MODE_PAGE_FLIP 0x01 + +struct drm_event_page_flip { + struct drm_event base; + uint64_t user_data; + uint32_t tv_sec; + uint32_t tv_usec; + uint32_t frame; +}; + /* typedef area */ #ifndef __KERNEL__ typedef struct drm_clip_rect drm_clip_rect_t; diff --git a/shared-core/drm_mode.h b/shared-core/drm_mode.h index 9b92733..bebe4e7 100644 --- a/shared-core/drm_mode.h +++ b/shared-core/drm_mode.h @@ -270,4 +270,20 @@ struct drm_mode_crtc_lut { uint64_t blue; }; +#define DRM_MODE_PAGE_FLIP_WAIT (1<<0) /* block on previous page flip */ +#define DRM_MODE_PAGE_FLIP_FLAGS_MASK (DRM_MODE_PAGE_FLIP_WAIT) + +struct drm_mode_page_flip { + /** Handle of new front buffer */ + uint32_t fb_id; + uint32_t crtc_id; + + /* 64 bit cookie returned to userspace in the page flip event. */ + uint64_t user_data; + /** + * page flip flags (wait on flip only for now) + */ + uint32_t flags; +}; + #endif