mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2025-12-20 15:10:10 +01:00
Encapsulate the drm event structure we read from the fd
This commit is contained in:
parent
a6196a85ca
commit
a470e8b0b4
4 changed files with 108 additions and 45 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,8 +463,8 @@ 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;
|
||||||
unsigned int *fb_ptr;
|
unsigned int *fb_ptr;
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue