diff options
-rw-r--r-- | libdrm/xf86drm.h | 18 | ||||
-rw-r--r-- | libdrm/xf86drmMode.c | 41 | ||||
-rw-r--r-- | shared-core/drm.h | 2 | ||||
-rw-r--r-- | tests/modetest/modetest.c | 92 |
4 files changed, 108 insertions, 45 deletions
diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h index c1d173c4..67bea37f 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 e8015e2d..f601a007 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -676,3 +676,44 @@ int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, void *user_data) 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/shared-core/drm.h b/shared-core/drm.h index 3b4b242e..8b504cb8 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -1140,13 +1140,13 @@ struct drm_gem_open { struct drm_event { uint32_t type; uint32_t length; - uint64_t user_data; }; #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; diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 6eed564e..a73dab1d 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -272,8 +272,9 @@ struct connector { drmModeModeInfo *mode; drmModeEncoder *encoder; int crtc; - unsigned int fb_id; + unsigned int fb_id[2], current_fb_id; struct timeval start; + int swap_count; }; @@ -462,8 +463,8 @@ create_test_buffer(drm_intel_bufmgr *bufmgr, #endif static int -create_black_buffer(drm_intel_bufmgr *bufmgr, - int width, int height, int *stride_out, drm_intel_bo **bo_out) +create_grey_buffer(drm_intel_bufmgr *bufmgr, + int width, int height, int *stride_out, drm_intel_bo **bo_out) { drm_intel_bo *bo; unsigned int *fb_ptr; @@ -488,7 +489,7 @@ create_black_buffer(drm_intel_bufmgr *bufmgr, return -1; } - memset(bo->virtual, 0, size); + memset(bo->virtual, 0x77, size); drm_intel_gem_bo_unmap_gtt(bo); *bo_out = bo; @@ -497,6 +498,39 @@ create_black_buffer(drm_intel_bufmgr *bufmgr, return 0; } +void +page_flip_handler(int fd, unsigned int frame, + unsigned int sec, unsigned int usec, void *data) +{ + struct connector *c; + unsigned int new_fb_id; + int len, ms; + struct drm_event_page_flip event; + struct timeval end; + double t; + + fprintf(stderr, "flip done, frame %d, time %d.%03d\n", + frame, sec % 100, usec / 1000); + + c = data; + if (c->current_fb_id == c->fb_id[0]) + new_fb_id = c->fb_id[1]; + else + new_fb_id = c->fb_id[0]; + + drmModePageFlip(fd, c->crtc, new_fb_id, c); + c->current_fb_id = new_fb_id; + c->swap_count++; + if (c->swap_count == 60) { + gettimeofday(&end, NULL); + t = end.tv_sec + end.tv_usec * 1e-6 - + (c->start.tv_sec + c->start.tv_usec * 1e-6); + fprintf(stderr, "freq: %.02fHz\n", c->swap_count / t); + c->swap_count = 0; + c->start = end; + } +} + static void set_mode(struct connector *c, int count, int page_flip) { @@ -507,6 +541,7 @@ set_mode(struct connector *c, int count, int page_flip) drm_intel_bo *bo, *other_bo; unsigned int fb_id, other_fb_id; int i, j, ret, width, height, x, stride; + drmEventContext evctx; width = 0; height = 0; @@ -546,7 +581,6 @@ set_mode(struct connector *c, int count, int page_flip) ret = drmModeSetCrtc(fd, c[i].crtc, fb_id, x, 0, &c[i].id, 1, c[i].mode); x += c[i].mode->hdisplay; - c[i].fb_id = fb_id; if (ret) { fprintf(stderr, "failed to set mode: %s\n", strerror(errno)); @@ -557,7 +591,7 @@ set_mode(struct connector *c, int count, int page_flip) if (!page_flip) return; - if (create_black_buffer(bufmgr, width, height, &stride, &other_bo)) + if (create_grey_buffer(bufmgr, width, height, &stride, &other_bo)) return; ret = drmModeAddFB(fd, width, height, 32, 32, stride, other_bo->handle, @@ -574,13 +608,16 @@ set_mode(struct connector *c, int count, int page_flip) drmModePageFlip(fd, c[i].crtc, other_fb_id, &c[i]); gettimeofday(&c[i].start, NULL); c[i].swap_count = 0; + c[i].fb_id[0] = fb_id; + c[i].fb_id[1] = other_fb_id; + c[i].current_fb_id = fb_id; } + memset(&evctx, 0, sizeof evctx); + evctx.version = DRM_EVENT_CONTEXT_VERSION; + evctx.page_flip_handler = page_flip_handler; + while (1) { - struct connector *c; - unsigned int new_fb_id; - int len, ms; - struct drm_event_page_flip event; struct pollfd pfd[2]; pfd[0].fd = 0; @@ -596,40 +633,7 @@ set_mode(struct connector *c, int count, int page_flip) if (pfd[0].revents) break; - len = read(fd, &event, sizeof event); - - if (len < sizeof event) - break; - if (event.base.type != DRM_EVENT_MODE_PAGE_FLIP) { - fprintf(stderr, - "got unhandled event %d\n", event.base.type); - continue; - } - - fprintf(stderr, "flip done, frame %d, time %d.%03d\n", - event.frame, event.tv_sec % 100, - event.tv_usec / 1000); - - c = (struct connector *) (long) event.base.user_data; - if (c->fb_id == fb_id) - new_fb_id = other_fb_id; - else - new_fb_id = fb_id; - - drmModePageFlip(fd, c->crtc, new_fb_id, c); - c->fb_id = new_fb_id; - c->swap_count++; - if (c->swap_count == 60) { - struct timeval end; - double t; - - gettimeofday(&end, NULL); - t = end.tv_sec + end.tv_usec * 1e-6 - - (c->start.tv_sec + c->start.tv_usec * 1e-6); - fprintf(stderr, "freq: %.02fHz\n", c->swap_count / t); - c->swap_count = 0; - c->start = end; - } + drmHandleEvent(fd, &evctx); } } |