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 "testdisplay.h"
#define TEST_DPMS 1
drmModeRes *resources;
int drm_fd;
int test_time = 3;
@ -58,25 +60,57 @@ struct test_output {
drmModeEncoder *encoder;
drmModeConnector *connector;
int crtc;
int pipe;
int flags;
unsigned int current_fb_id;
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,
unsigned int usec, void *data)
{
struct test_output *o = data;
unsigned int new_fb_id;
if (o->current_fb_id == o->fb_ids[0])
new_fb_id = o->fb_ids[1];
else
new_fb_id = o->fb_ids[0];
o->current_fb_id = !o->current_fb_id;
new_fb_id = o->fb_ids[o->current_fb_id];
drmModePageFlip(drm_fd, o->crtc, new_fb_id,
DRM_MODE_PAGE_FLIP_EVENT, o);
o->current_fb_id = new_fb_id;
printf("."); fflush(stdout);
if (o->flags & TEST_DPMS)
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)
@ -169,8 +203,6 @@ static void connector_find_preferred_mode(struct test_output *o, int crtc_id)
return;
}
o->pipe = i;
o->connector = connector;
}
@ -188,7 +220,19 @@ paint_flip_mode(cairo_t *cr, int width, int height, void *priv)
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 bpp = 32, depth = 24;
@ -201,6 +245,9 @@ static void set_mode(struct test_output *o, int crtc)
if (!o->mode_valid)
return;
fprintf(stdout, "Beginning page flipping on crtc %d, connector %d\n",
crtc, o->id);
width = o->mode.hdisplay;
height = o->mode.vdisplay;
@ -226,14 +273,14 @@ static void set_mode(struct test_output *o, int crtc)
strerror(errno));
exit(3);
}
assert(fb_is_bound(o, o->fb_ids[0]));
ret = drmModePageFlip(drm_fd, o->crtc, o->fb_ids[1],
DRM_MODE_PAGE_FLIP_EVENT, o);
if (ret) {
if (drmModePageFlip(drm_fd, o->crtc, o->fb_ids[1],
DRM_MODE_PAGE_FLIP_EVENT, o)) {
fprintf(stderr, "failed to page flip: %s\n", strerror(errno));
exit(4);
}
o->current_fb_id = o->fb_ids[1];
o->current_fb_id = 1;
memset(&evctx, 0, sizeof evctx);
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;
gettimeofday(&end, NULL);
end.tv_sec += 3;
end.tv_sec += duration;
while (1) {
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);
}
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);
drmModeFreeEncoder(o->encoder);
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;
resources = drmModeGetResources(drm_fd);
@ -289,15 +340,13 @@ static int run_test(void)
exit(5);
}
connectors = calloc(resources->count_connectors,
sizeof(struct test_output));
assert(connectors);
/* Find any connected displays */
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++)
set_mode(&connectors[c], resources->crtcs[i]);
flip_mode(&o, resources->crtcs[i], duration);
}
drmModeFreeResources(resources);
@ -306,9 +355,19 @@ static int run_test(void)
int main(int argc, char **argv)
{
struct {
int duration;
int flags;
} tests[] = {
{ 5, 0 },
{ 30, TEST_DPMS },
};
int i;
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);