diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-09-16 19:15:00 -0700 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-09-16 19:17:17 -0700 |
commit | 262220b8dedce190f189c42dec9696dd04e33b66 (patch) | |
tree | be93bf35a04322fc10c5d318ed2fc20803c2a06a | |
parent | 4ba680108ccd6e670ac516bfffd214251fb0eb83 (diff) | |
parent | a6196a85cae417ef973d26693e130a0ec032b8d9 (diff) |
Merge branch 'kms-pageflip' into vblank-event
Conflicts:
libdrm/xf86drmMode.c
shared-core/drm.h
tests/modetest/modetest.c
-rw-r--r-- | libdrm/xf86drmMode.c | 11 | ||||
-rw-r--r-- | libdrm/xf86drmMode.h | 3 | ||||
-rw-r--r-- | shared-core/drm.h | 11 | ||||
-rw-r--r-- | shared-core/drm_mode.h | 16 | ||||
-rw-r--r-- | tests/modetest/modetest.c | 135 |
5 files changed, 168 insertions, 8 deletions
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index 5fdcfa47..7d931704 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -707,3 +707,14 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx) 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); +} diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h index 62304bb9..fe647073 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 089e184a..a76a24c2 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -795,6 +795,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_PAGE_FLIP DRM_IOW( 0xB0, struct drm_mode_page_flip) /*@}*/ @@ -837,6 +838,16 @@ struct drm_event_vblank { uint32_t reserved; }; +#define DRM_EVENT_MODE_PAGE_FLIP 0x01 + +struct drm_event_page_flip { + struct drm_event base; + uint32_t tv_sec; + uint32_t tv_usec; + uint32_t frame; + uint64_t user_data; +}; + /* 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 9b92733d..bebe4e75 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 diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 6c69a570..8cddca76 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -46,6 +46,7 @@ #include <unistd.h> #include <string.h> #include <errno.h> +#include <sys/poll.h> #include "xf86drm.h" #include "xf86drmMode.h" @@ -271,6 +272,9 @@ struct connector { drmModeModeInfo *mode; drmModeEncoder *encoder; int crtc; + unsigned int fb_id; + struct timeval start; + int swap_count; }; static void @@ -457,15 +461,51 @@ 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) +{ + drm_intel_bo *bo; + unsigned int *fb_ptr; + int size, ret, i, stride; + div_t d; + + /* Mode size at 32 bpp */ + stride = width * 4; + size = stride * height; + + bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096); + if (!bo) { + fprintf(stderr, "failed to alloc buffer: %s\n", + strerror(errno)); + return -1; + } + + ret = drm_intel_gem_bo_map_gtt(bo); + if (ret) { + fprintf(stderr, "failed to GTT map buffer: %s\n", + strerror(errno)); + return -1; + } + + memset(bo->virtual, 0, size); + drm_intel_gem_bo_unmap_gtt(bo); + + *bo_out = bo; + *stride_out = stride; + + return 0; +} + static void -set_mode(struct connector *c, int count) +set_mode(struct connector *c, int count, int page_flip) { drmModeConnector *connector; drmModeEncoder *encoder = NULL; struct drm_mode_modeinfo *mode = NULL; drm_intel_bufmgr *bufmgr; - drm_intel_bo *bo; - unsigned int fb_id; + drm_intel_bo *bo, *other_bo; + unsigned int fb_id, other_fb_id; int i, j, ret, width, height, x, stride; width = 0; @@ -497,7 +537,6 @@ set_mode(struct connector *c, int count) x = 0; for (i = 0; i < count; i++) { - int crtc_id; if (c[i].mode == NULL) continue; @@ -507,17 +546,96 @@ set_mode(struct connector *c, int count) 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)); return; } } + + if (!page_flip) + return; + + if (create_black_buffer(bufmgr, width, height, &stride, &other_bo)) + return; + + ret = drmModeAddFB(fd, width, height, 32, 32, stride, other_bo->handle, + &other_fb_id); + if (ret) { + fprintf(stderr, "failed to add fb: %s\n", strerror(errno)); + return; + } + + for (i = 0; i < count; i++) { + if (c[i].mode == NULL) + continue; + + drmModePageFlip(fd, c[i].crtc, other_fb_id, &c[i]); + gettimeofday(&c[i].start, NULL); + c[i].swap_count = 0; + } + + 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; + pfd[0].events = POLLIN; + pfd[1].fd = fd; + pfd[1].events = POLLIN; + + if (poll(pfd, 2, -1) < 0) { + fprintf(stderr, "poll error\n"); + break; + } + + 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.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; + } + } } extern char *optarg; extern int optind, opterr, optopt; -static char optstr[] = "ecpmfs:"; +static char optstr[] = "ecpmfs:v"; void usage(char *name) { @@ -527,6 +645,7 @@ void usage(char *name) fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n"); fprintf(stderr, "\t-m\tlist modes\n"); fprintf(stderr, "\t-f\tlist framebuffers\n"); + fprintf(stderr, "\t-v\ttest vsynced page flipping\n"); fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n"); fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n"); fprintf(stderr, "\n\tDefault is to dump all info.\n"); @@ -539,6 +658,7 @@ int main(int argc, char **argv) { int c; int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0; + int test_vsync = 0; char *modules[] = { "i915", "radeon" }; char *modeset = NULL, *mode, *connector; int i, connector_id, count = 0; @@ -562,6 +682,9 @@ int main(int argc, char **argv) case 'f': framebuffers = 1; break; + case 'v': + test_vsync = 1; + break; case 's': modeset = strdup(optarg); con_args[count].crtc = -1; @@ -614,7 +737,7 @@ int main(int argc, char **argv) dump_resource(framebuffers); if (count > 0) { - set_mode(con_args, count); + set_mode(con_args, count, test_vsync); getchar(); } |