diff options
Diffstat (limited to 'tests/modetest/modetest.c')
-rw-r--r-- | tests/modetest/modetest.c | 272 |
1 files changed, 213 insertions, 59 deletions
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 193057ca..58e0e4cf 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -37,6 +37,8 @@ * TODO: use cairo to write the mode info on the selected output once * the mode has been programmed, along with possible test patterns. */ +#include "config.h" + #include <assert.h> #include <stdio.h> #include <stdlib.h> @@ -49,6 +51,11 @@ #include "xf86drmMode.h" #include "intel_bufmgr.h" +#ifdef HAVE_CAIRO +#include <math.h> +#include <cairo.h> +#endif + drmModeRes *resources; int fd, modes; @@ -131,7 +138,7 @@ void dump_encoders(void) printf("\n"); } -void dump_mode(struct drm_mode_modeinfo *mode) +void dump_mode(drmModeModeInfo *mode) { printf(" %s %.02f %d %d %d %d %d %d %d %d\n", mode->name, @@ -146,6 +153,19 @@ void dump_mode(struct drm_mode_modeinfo *mode) mode->vtotal); } +static void +dump_props(drmModeConnector *connector) +{ + drmModePropertyPtr props; + int i; + + for (i = 0; i < connector->count_props; i++) { + props = drmModeGetProperty(fd, connector->props[i]); + printf("\t%s, flags %d\n", props->name, props->flags); + drmModeFreeProperty(props); + } +} + void dump_connectors(void) { drmModeConnector *connector; @@ -180,6 +200,9 @@ void dump_connectors(void) dump_mode(&connector->modes[j]); drmModeFreeConnector(connector); + + printf(" props:\n"); + dump_props(connector); } printf("\n"); } @@ -242,17 +265,22 @@ void dump_framebuffers(void) * Then you need to find the encoder attached to that connector so you * can bind it with a free crtc. */ -void set_mode(int connector_id, char *mode_str) +struct connector { + int id; + char mode_str[64]; + drmModeModeInfo *mode; + drmModeEncoder *encoder; + int crtc; +}; + +static void +connector_find_mode(struct connector *c) { drmModeConnector *connector; - drmModeEncoder *encoder = NULL; - struct drm_mode_modeinfo *mode = NULL; - drm_intel_bufmgr *bufmgr; - drm_intel_bo *bo; - unsigned int fb_id, *fb_ptr; int i, j, size, ret, width, height; /* First, find the connector & mode */ + c->mode = NULL; for (i = 0; i < resources->count_connectors; i++) { connector = drmModeGetConnector(fd, resources->connectors[i]); @@ -268,96 +296,222 @@ void set_mode(int connector_id, char *mode_str) continue; } - if (connector->connector_id != connector_id) { + if (connector->connector_id != c->id) { drmModeFreeConnector(connector); continue; } for (j = 0; j < connector->count_modes; j++) { - mode = &connector->modes[j]; - if (!strcmp(mode->name, mode_str)) + c->mode = &connector->modes[j]; + if (!strcmp(c->mode->name, c->mode_str)) break; } /* Found it, break out */ - if (mode) + if (c->mode) break; drmModeFreeConnector(connector); } - if (!mode) { - fprintf(stderr, "failed to find mode \"%s\"\n", mode_str); + if (!c->mode) { + fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str); return; } - width = mode->hdisplay; - height = mode->vdisplay; - /* Now get the encoder */ for (i = 0; i < resources->count_encoders; i++) { - encoder = drmModeGetEncoder(fd, resources->encoders[i]); + c->encoder = drmModeGetEncoder(fd, resources->encoders[i]); - if (!encoder) { + if (!c->encoder) { fprintf(stderr, "could not get encoder %i: %s\n", resources->encoders[i], strerror(errno)); - drmModeFreeEncoder(encoder); + drmModeFreeEncoder(c->encoder); continue; } - if (encoder->encoder_id == connector->encoder_id) + if (c->encoder->encoder_id == connector->encoder_id) break; - drmModeFreeEncoder(encoder); + drmModeFreeEncoder(c->encoder); } - bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20); - if (!bufmgr) { - fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno)); - return; + if (c->crtc == -1) + c->crtc = c->encoder->crtc_id; +} + +#ifdef HAVE_CAIRO + +static int +create_test_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; + cairo_surface_t *surface; + cairo_t *cr; + char buf[64]; + int x, y; + + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + stride = cairo_image_surface_get_stride(surface); + size = stride * height; + fb_ptr = (unsigned int *) cairo_image_surface_get_data(surface); + + /* paint the buffer with colored tiles */ + for (i = 0; i < width * height; i++) { + d = div(i, width); + fb_ptr[i] = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6); } - /* Mode size at 32 bpp */ - size = width * height * 4; + cr = cairo_create(surface); + cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); + for (x = 0; x < width; x += 250) + for (y = 0; y < height; y += 250) { + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_move_to(cr, x, y - 20); + cairo_line_to(cr, x, y + 20); + cairo_move_to(cr, x - 20, y); + cairo_line_to(cr, x + 20, y); + cairo_new_sub_path(cr); + cairo_arc(cr, x, y, 10, 0, M_PI * 2); + cairo_set_line_width(cr, 4); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_stroke_preserve(cr); + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_set_line_width(cr, 2); + cairo_stroke(cr); + snprintf(buf, sizeof buf, "%d, %d", x, y); + cairo_move_to(cr, x + 20, y + 20); + cairo_text_path(cr, buf); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_stroke_preserve(cr); + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_fill(cr); + } + + cairo_destroy(cr); bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096); if (!bo) { fprintf(stderr, "failed to alloc buffer: %s\n", strerror(errno)); - return; + return -1; } - ret = drm_intel_bo_pin(bo, 4096); - if (ret) { - fprintf(stderr, "failed to pin buffer: %s\n", strerror(errno)); - return; + drm_intel_bo_subdata(bo, 0, size, fb_ptr); + + cairo_surface_destroy(surface); + + *bo_out = bo; + *stride_out = stride; + + return 0; +} + +#else + +static int +create_test_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; + return -1; } fb_ptr = bo->virtual; - /* paint the buffer blue */ - for (i = 0; i < width * height; i++) - fb_ptr[i] = 0xff; + /* paint the buffer with colored tiles */ + for (i = 0; i < width * height; i++) { + d = div(i, width); + fb_ptr[i] = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6); + } + drm_intel_bo_unmap(bo); + + *bo_out = bo; + *stride_out = stride; + + return 0; +} + +#endif + +static void +set_mode(struct connector *c, int count) +{ + drmModeConnector *connector; + drmModeEncoder *encoder = NULL; + struct drm_mode_modeinfo *mode = NULL; + drm_intel_bufmgr *bufmgr; + drm_intel_bo *bo; + unsigned int fb_id; + int i, j, ret, width, height, x, stride; + + width = 0; + height = 0; + for (i = 0; i < count; i++) { + connector_find_mode(&c[i]); + if (c[i].mode == NULL) + continue; + width += c[i].mode->hdisplay; + if (height < c[i].mode->vdisplay) + height = c[i].mode->vdisplay; + } + + bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20); + if (!bufmgr) { + fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno)); + return; + } - ret = drmModeAddFB(fd, width, height, 32, 32, width * 4, bo->handle, + if (create_test_buffer(bufmgr, width, height, &stride, &bo)) + return; + + 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; } - ret = drmModeSetCrtc(fd, encoder->crtc_id, fb_id, 0, 0, - &connector->connector_id, 1, mode); - if (ret) { - fprintf(stderr, "failed to set mode: %s\n", strerror(errno)); - return; + x = 0; + for (i = 0; i < count; i++) { + int crtc_id; + if (c[i].mode == NULL) + continue; + + printf("setting mode %s on connector %d, crtc %d\n", + c[i].mode_str, c[i].id, c[i].crtc); + + ret = drmModeSetCrtc(fd, c[i].crtc, fb_id, x, 0, + &c[i].id, 1, c[i].mode); + x += c[i].mode->hdisplay; + + if (ret) { + fprintf(stderr, "failed to set mode: %s\n", strerror(errno)); + return; + } } } @@ -374,6 +528,7 @@ void usage(char *name) fprintf(stderr, "\t-m\tlist modes\n"); fprintf(stderr, "\t-f\tlist framebuffers\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"); exit(0); } @@ -386,8 +541,9 @@ int main(int argc, char **argv) int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0; char *modules[] = { "i915", "radeon" }; char *modeset = NULL, *mode, *connector; - int i, connector_id; - + int i, connector_id, count = 0; + struct connector con_args[2]; + opterr = 0; while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { @@ -408,6 +564,16 @@ int main(int argc, char **argv) break; case 's': modeset = strdup(optarg); + con_args[count].crtc = -1; + if (sscanf(optarg, "%d:%64s", + &con_args[count].id, + &con_args[count].mode_str) != 2 && + sscanf(optarg, "%d@%d:%64s", + &con_args[count].id, + &con_args[count].crtc, + &con_args[count].mode_str) != 3) + usage(argv[0]); + count++; break; default: usage(argv[0]); @@ -447,23 +613,11 @@ int main(int argc, char **argv) dump_resource(crtcs); dump_resource(framebuffers); - if (modeset) { - connector = strtok(modeset, ":"); - if (!connector) - usage(argv[0]); - connector_id = atoi(connector); - - mode = strtok(NULL, ":"); - if (!mode) - usage(argv[0]); - printf("setting connector %d to mode %s\n", connector_id, - mode); - set_mode(connector_id, mode); - sleep(3); + if (count > 0) { + set_mode(con_args, count); + getchar(); } - sleep(3); - drmModeFreeResources(resources); return 0; |