Add a test case into intel-gpu-tools for intel display driver validation.

We have not a unified tool to check Intel display driver and we plan to use
intel-gpu-tools/testdisplay to check Intel display driver even though some
function tests can be found in libdrm/test. 3 new features are added:test
all supported modes, force mode and dump mode info(dump mode info is based on
libdrm/tests/modetest).

[ickle: attack the whitespacing!]
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Hai Lan 2011-02-11 11:14:15 -05:00 committed by Chris Wilson
parent d75f2632c1
commit 62d516813a

View File

@ -69,6 +69,18 @@
struct udev_monitor *uevent_monitor; struct udev_monitor *uevent_monitor;
drmModeRes *resources; drmModeRes *resources;
int fd, modes; int fd, modes;
int dump_info = 0, test_all_modes =0, test_preferred_mode = 0, force_mode = 0;
int sleep_between_modes = 5;
float force_clock;
int force_hdisplay;
int force_hsync_start;
int force_hsync_end;
int force_htotal;
int force_vdisplay;
int force_vsync_start;
int force_vsync_end;
int force_vtotal;
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@ -141,6 +153,86 @@ struct connector {
int crtc; int crtc;
}; };
static void dump_mode(drmModeModeInfo *mode)
{
printf(" %s %d %d %d %d %d %d %d %d %d\n",
mode->name,
mode->vrefresh,
mode->hdisplay,
mode->hsync_start,
mode->hsync_end,
mode->htotal,
mode->vdisplay,
mode->vsync_start,
mode->vsync_end,
mode->vtotal);
}
static void dump_connectors(void)
{
int i, j;
printf("Connectors:\n");
printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n");
for (i = 0; i < resources->count_connectors; i++) {
drmModeConnector *connector;
connector = drmModeGetConnector(fd, resources->connectors[i]);
if (!connector) {
fprintf(stderr, "could not get connector %i: %s\n",
resources->connectors[i], strerror(errno));
continue;
}
printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n",
connector->connector_id,
connector->encoder_id,
connector_status_str(connector->connection),
connector_type_str(connector->connector_type),
connector->mmWidth, connector->mmHeight,
connector->count_modes);
if (!connector->count_modes)
continue;
printf(" modes:\n");
printf(" name refresh (Hz) hdisp hss hse htot vdisp "
"vss vse vtot)\n");
for (j = 0; j < connector->count_modes; j++)
dump_mode(&connector->modes[j]);
drmModeFreeConnector(connector);
}
printf("\n");
}
static void dump_crtcs(void)
{
int i;
printf("CRTCs:\n");
printf("id\tfb\tpos\tsize\n");
for (i = 0; i < resources->count_crtcs; i++) {
drmModeCrtc *crtc;
crtc = drmModeGetCrtc(fd, resources->crtcs[i]);
if (!crtc) {
fprintf(stderr, "could not get crtc %i: %s\n",
resources->crtcs[i], strerror(errno));
continue;
}
printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
crtc->crtc_id,
crtc->buffer_id,
crtc->x, crtc->y,
crtc->width, crtc->height);
dump_mode(&crtc->mode);
drmModeFreeCrtc(crtc);
}
printf("\n");
}
static void connector_find_preferred_mode(struct connector *c) static void connector_find_preferred_mode(struct connector *c)
{ {
drmModeConnector *connector; drmModeConnector *connector;
@ -420,6 +512,7 @@ set_mode(struct connector *c)
cairo_surface_t *surface; cairo_surface_t *surface;
cairo_t *cr; cairo_t *cr;
char buf[128]; char buf[128];
int j, test_mode_num;
width = 0; width = 0;
height = 0; height = 0;
@ -427,62 +520,91 @@ set_mode(struct connector *c)
if (!c->mode_valid) if (!c->mode_valid)
return; return;
width += c->mode.hdisplay; if (test_preferred_mode || force_mode)
if (height < c->mode.vdisplay) test_mode_num = 1;
height = c->mode.vdisplay; if (test_all_modes)
test_mode_num = c->connector->count_modes;
bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20); for (j = 0; j < test_mode_num; j++) {
if (!bufmgr) { if (test_all_modes)
fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno)); c->mode = c->connector->modes[j];
return; width = 0;
height = 0;
width += c->mode.hdisplay;
if (height < c->mode.vdisplay)
height = c->mode.vdisplay;
if (force_mode){
width = force_hdisplay;
height = force_vdisplay;
c->mode.clock = force_clock*1000;
c->mode.hdisplay = force_hdisplay;
c->mode.hsync_start = force_hsync_start;
c->mode.hsync_end = force_hsync_end;
c->mode.htotal = force_htotal;
c->mode.vdisplay = force_vdisplay;
c->mode.vsync_start = force_vsync_start;
c->mode.vsync_end = force_vsync_end;
c->mode.vtotal = force_vtotal;
c->mode.vrefresh =(force_clock*1e6)/(force_htotal*force_vtotal);
sprintf(c->mode.name,"%d%s%d",width,"x",height);
}
bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20);
if (!bufmgr) {
fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno));
return;
}
if (create_test_buffer(bufmgr, width, height, &stride, &bo))
return;
surface = cairo_image_surface_create_for_data(bo->virtual,
CAIRO_FORMAT_ARGB32,
width, height,
stride);
cr = cairo_create(surface);
cairo_surface_destroy(surface);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
/* Paint corner markers */
snprintf(buf, sizeof buf, "(%d, %d)", 0, 0);
paint_marker(cr, 0, 0, buf, bottomright);
snprintf(buf, sizeof buf, "(%d, %d)", width, 0);
paint_marker(cr, width, 0, buf, bottomleft);
snprintf(buf, sizeof buf, "(%d, %d)", 0, height);
paint_marker(cr, 0, height, buf, topright);
snprintf(buf, sizeof buf, "(%d, %d)", width, height);
paint_marker(cr, width, height, buf, topleft);
/* Paint output info */
paint_output_info(cr, c, width, height);
cairo_destroy(cr);
drm_intel_gem_bo_unmap_gtt(bo);
ret = drmModeAddFB(fd, width, height, 32, 32, stride, bo->handle,
&fb_id);
if (ret) {
fprintf(stderr, "failed to add fb (width=%d, height=%d): %s\n",
width, height, strerror(errno));
return;
}
if (!c->mode_valid)
return;
dump_mode(&c->mode);
ret = drmModeSetCrtc(fd, c->crtc, fb_id, 0, 0,
&c->id, 1, &c->mode);
if (ret) {
fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
return;
}
if (sleep_between_modes && test_all_modes)
sleep(5);
} }
if (create_test_buffer(bufmgr, width, height, &stride, &bo))
return;
surface = cairo_image_surface_create_for_data(bo->virtual,
CAIRO_FORMAT_ARGB32,
width, height,
stride);
cr = cairo_create(surface);
cairo_surface_destroy(surface);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
/* Paint corner markers */
snprintf(buf, sizeof buf, "(%d, %d)", 0, 0);
paint_marker(cr, 0, 0, buf, bottomright);
snprintf(buf, sizeof buf, "(%d, %d)", width, 0);
paint_marker(cr, width, 0, buf, bottomleft);
snprintf(buf, sizeof buf, "(%d, %d)", 0, height);
paint_marker(cr, 0, height, buf, topright);
snprintf(buf, sizeof buf, "(%d, %d)", width, height);
paint_marker(cr, width, height, buf, topleft);
/* Paint output info */
paint_output_info(cr, c, width, height);
cairo_destroy(cr);
drm_intel_gem_bo_unmap_gtt(bo);
ret = drmModeAddFB(fd, width, height, 32, 32, stride, bo->handle,
&fb_id);
if (ret) {
fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
return;
}
if (!c->mode_valid)
return;
ret = drmModeSetCrtc(fd, c->crtc, fb_id, 0, 0,
&c->id, 1, &c->mode);
if (ret) {
fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
return;
}
drmModeFreeEncoder(c->encoder); drmModeFreeEncoder(c->encoder);
drmModeFreeConnector(c->connector); drmModeFreeConnector(c->connector);
} }
@ -513,24 +635,41 @@ static void update_display(void)
if (!connectors) if (!connectors)
return; return;
/* Find any connected displays */ if (dump_info) {
for (c = 0; c < resources->count_connectors; c++) { dump_connectors();
connectors[c].id = resources->connectors[c]; dump_crtcs();
set_mode(&connectors[c]); }
if (test_preferred_mode || test_all_modes || force_mode) {
/* Find any connected displays */
for (c = 0; c < resources->count_connectors; c++) {
connectors[c].id = resources->connectors[c];
set_mode(&connectors[c]);
}
} }
drmModeFreeResources(resources); drmModeFreeResources(resources);
if (dump_info || test_all_modes)
exit(0);
} }
extern char *optarg; extern char *optarg;
extern int optind, opterr, optopt; extern int optind, opterr, optopt;
static char optstr[] = "h"; static char optstr[] = "hiaf:s:";
static void usage(char *name) static void usage(char *name)
{ {
fprintf(stderr, "usage: %s [-h]\n", name); fprintf(stderr, "usage: %s [-hiafs]\n", name);
fprintf(stderr, "\t-i\tdump info\n");
fprintf(stderr, "\t-a\ttest all modes\n");
fprintf(stderr, "\t-s\t<duration>\tsleep between each mode test\n");
fprintf(stderr, "\t-f\t<clock MHz>,<hdisp>,<hsync-start>,<hsync-end>,<htotal>,\n");
fprintf(stderr, "\t\t<vdisp>,<vsync-start>,<vsync-end>,<vtotal>\n");
fprintf(stderr, "\t\ttest force mode\n");
fprintf(stderr, "\tDefault is to test the preferred mode.\n");
exit(0); exit(0);
} }
#define dump_resource(res) if (res) dump_##res()
static gboolean hotplug_event(GIOChannel *source, GIOCondition condition, static gboolean hotplug_event(GIOChannel *source, GIOCondition condition,
gpointer data) gpointer data)
{ {
@ -590,6 +729,23 @@ int main(int argc, char **argv)
opterr = 0; opterr = 0;
while ((c = getopt(argc, argv, optstr)) != -1) { while ((c = getopt(argc, argv, optstr)) != -1) {
switch (c) { switch (c) {
case 'i':
dump_info = 1;
encoders = connectors = crtcs = modes = framebuffers = 1;
break;
case 'a':
test_all_modes = 1;
break;
case 'f':
force_mode = 1;
if(sscanf(optarg,"%f,%d,%d,%d,%d,%d,%d,%d,%d",
&force_clock,&force_hdisplay, &force_hsync_start,&force_hsync_end,&force_htotal,
&force_vdisplay, &force_vsync_start, &force_vsync_end, &force_vtotal)!= 9)
usage(argv[0]);
break;
case 's':
sleep_between_modes = atoi(optarg);
break;
default: default:
fprintf(stderr, "unknown option %c\n", c); fprintf(stderr, "unknown option %c\n", c);
/* fall through */ /* fall through */
@ -598,9 +754,8 @@ int main(int argc, char **argv)
break; break;
} }
} }
if (argc == 1) if (argc == 1)
encoders = connectors = crtcs = modes = framebuffers = 1; test_preferred_mode = 1;
for (i = 0; i < ARRAY_SIZE(modules); i++) { for (i = 0; i < ARRAY_SIZE(modules); i++) {
fd = drmOpen(modules[i], NULL); fd = drmOpen(modules[i], NULL);