Encapsulate the drm event structure we read from the fd

This commit is contained in:
Kristian Høgsberg 2009-05-27 17:40:50 -04:00
parent a6196a85ca
commit a470e8b0b4
4 changed files with 108 additions and 45 deletions

View file

@ -667,4 +667,22 @@ extern void drmMsg(const char *format, ...);
extern int drmSetMaster(int fd); extern int drmSetMaster(int fd);
extern int drmDropMaster(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 #endif

View file

@ -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); 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;
}

View file

@ -1140,13 +1140,13 @@ struct drm_gem_open {
struct drm_event { struct drm_event {
uint32_t type; uint32_t type;
uint32_t length; uint32_t length;
uint64_t user_data;
}; };
#define DRM_EVENT_MODE_PAGE_FLIP 0x01 #define DRM_EVENT_MODE_PAGE_FLIP 0x01
struct drm_event_page_flip { struct drm_event_page_flip {
struct drm_event base; struct drm_event base;
uint64_t user_data;
uint32_t tv_sec; uint32_t tv_sec;
uint32_t tv_usec; uint32_t tv_usec;
uint32_t frame; uint32_t frame;

View file

@ -272,8 +272,9 @@ struct connector {
drmModeModeInfo *mode; drmModeModeInfo *mode;
drmModeEncoder *encoder; drmModeEncoder *encoder;
int crtc; int crtc;
unsigned int fb_id; unsigned int fb_id[2], current_fb_id;
struct timeval start; struct timeval start;
int swap_count; int swap_count;
}; };
@ -462,7 +463,7 @@ create_test_buffer(drm_intel_bufmgr *bufmgr,
#endif #endif
static int static int
create_black_buffer(drm_intel_bufmgr *bufmgr, create_grey_buffer(drm_intel_bufmgr *bufmgr,
int width, int height, int *stride_out, drm_intel_bo **bo_out) int width, int height, int *stride_out, drm_intel_bo **bo_out)
{ {
drm_intel_bo *bo; drm_intel_bo *bo;
@ -488,7 +489,7 @@ create_black_buffer(drm_intel_bufmgr *bufmgr,
return -1; return -1;
} }
memset(bo->virtual, 0, size); memset(bo->virtual, 0x77, size);
drm_intel_gem_bo_unmap_gtt(bo); drm_intel_gem_bo_unmap_gtt(bo);
*bo_out = bo; *bo_out = bo;
@ -497,6 +498,39 @@ create_black_buffer(drm_intel_bufmgr *bufmgr,
return 0; 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 static void
set_mode(struct connector *c, int count, int page_flip) 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; drm_intel_bo *bo, *other_bo;
unsigned int fb_id, other_fb_id; unsigned int fb_id, other_fb_id;
int i, j, ret, width, height, x, stride; int i, j, ret, width, height, x, stride;
drmEventContext evctx;
width = 0; width = 0;
height = 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, ret = drmModeSetCrtc(fd, c[i].crtc, fb_id, x, 0,
&c[i].id, 1, c[i].mode); &c[i].id, 1, c[i].mode);
x += c[i].mode->hdisplay; x += c[i].mode->hdisplay;
c[i].fb_id = fb_id;
if (ret) { if (ret) {
fprintf(stderr, "failed to set mode: %s\n", strerror(errno)); 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) if (!page_flip)
return; return;
if (create_black_buffer(bufmgr, width, height, &stride, &other_bo)) if (create_grey_buffer(bufmgr, width, height, &stride, &other_bo))
return; return;
ret = drmModeAddFB(fd, width, height, 32, 32, stride, other_bo->handle, 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]); drmModePageFlip(fd, c[i].crtc, other_fb_id, &c[i]);
gettimeofday(&c[i].start, NULL); gettimeofday(&c[i].start, NULL);
c[i].swap_count = 0; 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) { while (1) {
struct connector *c;
unsigned int new_fb_id;
int len, ms;
struct drm_event_page_flip event;
struct pollfd pfd[2]; struct pollfd pfd[2];
pfd[0].fd = 0; pfd[0].fd = 0;
@ -596,40 +633,7 @@ set_mode(struct connector *c, int count, int page_flip)
if (pfd[0].revents) if (pfd[0].revents)
break; break;
len = read(fd, &event, sizeof event); drmHandleEvent(fd, &evctx);
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;
}
} }
} }