tests/flip_test: Revamp to demonstrate race with modeset/dpms and pageflips

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-09-28 13:03:02 +01:00
parent 4650505d7e
commit a65087a26e

View File

@ -38,6 +38,8 @@
#include "drmtest.h" #include "drmtest.h"
#include "testdisplay.h" #include "testdisplay.h"
#define TEST_DPMS 1
drmModeRes *resources; drmModeRes *resources;
int drm_fd; int drm_fd;
int test_time = 3; int test_time = 3;
@ -58,25 +60,57 @@ struct test_output {
drmModeEncoder *encoder; drmModeEncoder *encoder;
drmModeConnector *connector; drmModeConnector *connector;
int crtc; int crtc;
int pipe; int flags;
unsigned int current_fb_id; unsigned int current_fb_id;
unsigned int fb_ids[2]; unsigned int fb_ids[2];
}; };
static int set_dpms(struct test_output *o, int mode)
{
int i, dpms = 0;
for (i = 0; i < o->connector->count_props; i++) {
struct drm_mode_get_property prop;
prop.prop_id = o->connector->props[i];
prop.count_values = 0;
prop.count_enum_blobs = 0;
if (drmIoctl(drm_fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
continue;
if (strcmp(prop.name, "DPMS"))
continue;
dpms = prop.prop_id;
break;
}
if (!dpms) {
fprintf(stderr, "DPMS property not found on %d\n", o->id);
errno = ENOENT;
return -1;
}
return drmModeConnectorSetProperty(drm_fd, o->id, dpms, mode);
}
static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
unsigned int usec, void *data) unsigned int usec, void *data)
{ {
struct test_output *o = data; struct test_output *o = data;
unsigned int new_fb_id; unsigned int new_fb_id;
if (o->current_fb_id == o->fb_ids[0]) o->current_fb_id = !o->current_fb_id;
new_fb_id = o->fb_ids[1]; new_fb_id = o->fb_ids[o->current_fb_id];
else
new_fb_id = o->fb_ids[0];
drmModePageFlip(drm_fd, o->crtc, new_fb_id, printf("."); fflush(stdout);
DRM_MODE_PAGE_FLIP_EVENT, o); if (o->flags & TEST_DPMS)
o->current_fb_id = new_fb_id; do_or_die(set_dpms(o, 0));
do_or_die(drmModePageFlip(drm_fd, o->crtc, new_fb_id,
DRM_MODE_PAGE_FLIP_EVENT, o));
if (o->flags & TEST_DPMS)
do_or_die(set_dpms(o, 3));
} }
static void connector_find_preferred_mode(struct test_output *o, int crtc_id) static void connector_find_preferred_mode(struct test_output *o, int crtc_id)
@ -169,8 +203,6 @@ static void connector_find_preferred_mode(struct test_output *o, int crtc_id)
return; return;
} }
o->pipe = i;
o->connector = connector; o->connector = connector;
} }
@ -188,7 +220,19 @@ paint_flip_mode(cairo_t *cr, int width, int height, void *priv)
cairo_fill(cr); cairo_fill(cr);
} }
static void set_mode(struct test_output *o, int crtc) static int
fb_is_bound(struct test_output *o, int fb)
{
struct drm_mode_crtc mode;
mode.crtc_id = o->crtc;
if (drmIoctl(drm_fd, DRM_IOCTL_MODE_GETCRTC, &mode))
return 0;
return mode.mode_valid && mode.fb_id == fb;
}
static void flip_mode(struct test_output *o, int crtc, int duration)
{ {
int ret; int ret;
int bpp = 32, depth = 24; int bpp = 32, depth = 24;
@ -201,6 +245,9 @@ static void set_mode(struct test_output *o, int crtc)
if (!o->mode_valid) if (!o->mode_valid)
return; return;
fprintf(stdout, "Beginning page flipping on crtc %d, connector %d\n",
crtc, o->id);
width = o->mode.hdisplay; width = o->mode.hdisplay;
height = o->mode.vdisplay; height = o->mode.vdisplay;
@ -226,14 +273,14 @@ static void set_mode(struct test_output *o, int crtc)
strerror(errno)); strerror(errno));
exit(3); exit(3);
} }
assert(fb_is_bound(o, o->fb_ids[0]));
ret = drmModePageFlip(drm_fd, o->crtc, o->fb_ids[1], if (drmModePageFlip(drm_fd, o->crtc, o->fb_ids[1],
DRM_MODE_PAGE_FLIP_EVENT, o); DRM_MODE_PAGE_FLIP_EVENT, o)) {
if (ret) {
fprintf(stderr, "failed to page flip: %s\n", strerror(errno)); fprintf(stderr, "failed to page flip: %s\n", strerror(errno));
exit(4); exit(4);
} }
o->current_fb_id = o->fb_ids[1]; o->current_fb_id = 1;
memset(&evctx, 0, sizeof evctx); memset(&evctx, 0, sizeof evctx);
evctx.version = DRM_EVENT_CONTEXT_VERSION; evctx.version = DRM_EVENT_CONTEXT_VERSION;
@ -241,7 +288,7 @@ static void set_mode(struct test_output *o, int crtc)
evctx.page_flip_handler = page_flip_handler; evctx.page_flip_handler = page_flip_handler;
gettimeofday(&end, NULL); gettimeofday(&end, NULL);
end.tv_sec += 3; end.tv_sec += duration;
while (1) { while (1) {
struct timeval now, timeout = { .tv_sec = 3, .tv_usec = 0 }; struct timeval now, timeout = { .tv_sec = 3, .tv_usec = 0 };
@ -270,16 +317,20 @@ static void set_mode(struct test_output *o, int crtc)
drmHandleEvent(drm_fd, &evctx); drmHandleEvent(drm_fd, &evctx);
} }
fprintf(stdout, "page flipping on crtc %d, connector %d: PASSED\n", /* and drain the event queue */
evctx.page_flip_handler = NULL;
drmHandleEvent(drm_fd, &evctx);
fprintf(stdout, "\npage flipping on crtc %d, connector %d: PASSED\n",
crtc, o->id); crtc, o->id);
drmModeFreeEncoder(o->encoder); drmModeFreeEncoder(o->encoder);
drmModeFreeConnector(o->connector); drmModeFreeConnector(o->connector);
} }
static int run_test(void) static int run_test(int duration, int flags)
{ {
struct test_output *connectors; struct test_output o;
int c, i; int c, i;
resources = drmModeGetResources(drm_fd); resources = drmModeGetResources(drm_fd);
@ -289,15 +340,13 @@ static int run_test(void)
exit(5); exit(5);
} }
connectors = calloc(resources->count_connectors,
sizeof(struct test_output));
assert(connectors);
/* Find any connected displays */ /* Find any connected displays */
for (c = 0; c < resources->count_connectors; c++) { for (c = 0; c < resources->count_connectors; c++) {
connectors[c].id = resources->connectors[c]; memset(&o, 0, sizeof(o));
o.id = resources->connectors[c];
o.flags = flags;
for (i = 0; i < resources->count_crtcs; i++) for (i = 0; i < resources->count_crtcs; i++)
set_mode(&connectors[c], resources->crtcs[i]); flip_mode(&o, resources->crtcs[i], duration);
} }
drmModeFreeResources(resources); drmModeFreeResources(resources);
@ -306,9 +355,19 @@ static int run_test(void)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct {
int duration;
int flags;
} tests[] = {
{ 5, 0 },
{ 30, TEST_DPMS },
};
int i;
drm_fd = drm_open_any(); drm_fd = drm_open_any();
run_test(); for (i = 0; i < sizeof(tests) / sizeof (tests[0]); i++)
run_test(tests[i].duration, tests[i].flags);
close(drm_fd); close(drm_fd);