From 731cd5526e5c732d51307b26e784f454a724a699 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 17 Dec 2008 10:09:49 -0800 Subject: libdrm: add mode setting files Add mode setting files to libdrm, including xf86drmMode.* and the new drm_mode.h header. Also add a couple of tests to sanity check the kernel interfaces and update code to support them. --- tests/Makefile.am | 4 + tests/dristat.c | 2 +- tests/modeprint/Makefile | 14 ++ tests/modeprint/app | Bin 0 -> 16233 bytes tests/modeprint/modeprint.c | 402 +++++++++++++++++++++++++++++++++++++++ tests/modeprint/test | 1 + tests/modetest/Makefile | 14 ++ tests/modetest/modetest.c | 449 ++++++++++++++++++++++++++++++++++++++++++++ tests/modetest/test | 2 + 9 files changed, 887 insertions(+), 1 deletion(-) create mode 100644 tests/modeprint/Makefile create mode 100755 tests/modeprint/app create mode 100644 tests/modeprint/modeprint.c create mode 100644 tests/modeprint/test create mode 100644 tests/modetest/Makefile create mode 100644 tests/modetest/modetest.c create mode 100644 tests/modetest/test (limited to 'tests') diff --git a/tests/Makefile.am b/tests/Makefile.am index 95f0f22e..02b2ef0a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -15,6 +15,10 @@ libdrmtest_la_LIBADD = \ LDADD = libdrmtest.la +noinst_SUBDIRS = \ + modeprint \ + modetest + TESTS = auth \ openclose \ getversion \ diff --git a/tests/dristat.c b/tests/dristat.c index 89853164..48c3b51b 100644 --- a/tests/dristat.c +++ b/tests/dristat.c @@ -263,7 +263,7 @@ int main(int argc, char **argv) for (i = 0; i < 16; i++) if (!minor || i == minor) { sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i); - fd = drmOpenMinor(i, 1); + fd = drmOpenMinor(i, 1, DRM_NODE_RENDER); if (fd >= 0) { printf("%s\n", buf); if (mask & DRM_BUSID) getbusid(fd); diff --git a/tests/modeprint/Makefile b/tests/modeprint/Makefile new file mode 100644 index 00000000..70788dc9 --- /dev/null +++ b/tests/modeprint/Makefile @@ -0,0 +1,14 @@ + +all: app + +#CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \ +# -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \ + +app: modeprint.c + @gcc $(CFLAGS) -o app -Wall -I../../libdrm -I../../shared-core -L../../libdrm/.libs -ldrm modeprint.c + +clean: + @rm -f app + +run: app + @sudo ./test diff --git a/tests/modeprint/app b/tests/modeprint/app new file mode 100755 index 00000000..82085c85 Binary files /dev/null and b/tests/modeprint/app differ diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c new file mode 100644 index 00000000..595d4447 --- /dev/null +++ b/tests/modeprint/modeprint.c @@ -0,0 +1,402 @@ +/* + * \file modedemo.c + * Test program to dump DRM kernel mode setting related information. + * Queries the kernel for all available information and dumps it to stdout. + * + * \author Jakob Bornecrantz + */ + +/* + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright (c) 2007-2008 Jakob Bornecrantz + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "xf86drm.h" +#include "xf86drmMode.h" + +int connectors; +int full_props; +int edid; +int modes; +int full_modes; +int encoders; +int crtcs; +int fbs; +char *module_name; + +const char* getConnectionText(drmModeConnection conn) +{ + switch (conn) { + case DRM_MODE_CONNECTED: + return "connected"; + case DRM_MODE_DISCONNECTED: + return "disconnected"; + default: + return "unknown"; + } + +} + +int printMode(struct drm_mode_modeinfo *mode) +{ + if (full_modes) { + printf("Mode: %s\n", mode->name); + printf("\tclock : %i\n", mode->clock); + printf("\thdisplay : %i\n", mode->hdisplay); + printf("\thsync_start : %i\n", mode->hsync_start); + printf("\thsync_end : %i\n", mode->hsync_end); + printf("\thtotal : %i\n", mode->htotal); + printf("\thskew : %i\n", mode->hskew); + printf("\tvdisplay : %i\n", mode->vdisplay); + printf("\tvsync_start : %i\n", mode->vsync_start); + printf("\tvsync_end : %i\n", mode->vsync_end); + printf("\tvtotal : %i\n", mode->vtotal); + printf("\tvscan : %i\n", mode->vscan); + printf("\tvrefresh : %i\n", mode->vrefresh); + printf("\tflags : %i\n", mode->flags); + } else { + printf("Mode: \"%s\" %ix%i %.0f\n", mode->name, + mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000.0); + } + return 0; +} + +int printProperty(int fd, drmModeResPtr res, drmModePropertyPtr props, uint64_t value) +{ + const unsigned char *name = NULL; + int j; + + printf("Property: %s\n", props->name); + printf("\tid : %i\n", props->prop_id); + printf("\tflags : %i\n", props->flags); + printf("\tcount_values : %d\n", props->count_values); + + + if (props->count_values) { + printf("\tvalues :"); + for (j = 0; j < props->count_values; j++) + printf(" %lld", props->values[j]); + printf("\n"); + } + + + printf("\tcount_enums : %d\n", props->count_enums); + + if (props->flags & DRM_MODE_PROP_BLOB) { + drmModePropertyBlobPtr blob; + + blob = drmModeGetPropertyBlob(fd, value); + if (blob) { + printf("blob is %d length, %08X\n", blob->length, *(uint32_t *)blob->data); + drmModeFreePropertyBlob(blob); + } else { + printf("error getting blob %lld\n", value); + } + + } else { + if (!strncmp(props->name, "DPMS", 4)) + ; + + for (j = 0; j < props->count_enums; j++) { + printf("\t\t%lld = %s\n", props->enums[j].value, props->enums[j].name); + if (props->enums[j].value == value) + name = props->enums[j].name; + } + + if (props->count_enums && name) { + printf("\tcon_value : %s\n", name); + } else { + printf("\tcon_value : %lld\n", value); + } + } + + return 0; +} + +int printConnector(int fd, drmModeResPtr res, drmModeConnectorPtr connector, uint32_t id) +{ + int i = 0; + struct drm_mode_modeinfo *mode = NULL; + drmModePropertyPtr props; + + printf("Connector: %d-%d\n", connector->connector_type, connector->connector_type_id); + printf("\tid : %i\n", id); + printf("\tencoder id : %i\n", connector->encoder_id); + printf("\tconn : %s\n", getConnectionText(connector->connection)); + printf("\tsize : %ix%i (mm)\n", connector->mmWidth, connector->mmHeight); + printf("\tcount_modes : %i\n", connector->count_modes); + printf("\tcount_props : %i\n", connector->count_props); + if (connector->count_props) { + printf("\tprops :"); + for (i = 0; i < connector->count_props; i++) + printf(" %i", connector->props[i]); + printf("\n"); + } + + printf("\tcount_encoders : %i\n", connector->count_encoders); + if (connector->count_encoders) { + printf("\tencoders :"); + for (i = 0; i < connector->count_encoders; i++) + printf(" %i", connector->encoders[i]); + printf("\n"); + } + + if (modes) { + for (i = 0; i < connector->count_modes; i++) { + mode = &connector->modes[i]; + printMode(mode); + } + } + + if (full_props) { + for (i = 0; i < connector->count_props; i++) { + props = drmModeGetProperty(fd, connector->props[i]); + if (props) { + printProperty(fd, res, props, connector->prop_values[i]); + drmModeFreeProperty(props); + } + } + } + + return 0; +} + +int printEncoder(int fd, drmModeResPtr res, drmModeEncoderPtr encoder, uint32_t id) +{ + printf("Encoder\n"); + printf("\tid :%i\n", id); + printf("\tcrtc_id :%d\n", encoder->crtc_id); + printf("\ttype :%d\n", encoder->encoder_type); + printf("\tpossible_crtcs :%d\n", encoder->possible_crtcs); + printf("\tpossible_clones :%d\n", encoder->possible_clones); + return 0; +} + +int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id) +{ + printf("Crtc\n"); + printf("\tid : %i\n", id); + printf("\tx : %i\n", crtc->x); + printf("\ty : %i\n", crtc->y); + printf("\twidth : %i\n", crtc->width); + printf("\theight : %i\n", crtc->height); + printf("\tmode : %p\n", &crtc->mode); + printf("\tgamma size : %d\n", crtc->gamma_size); + + return 0; +} + +int printFrameBuffer(int fd, drmModeResPtr res, drmModeFBPtr fb) +{ + printf("Framebuffer\n"); + printf("\thandle : %i\n", fb->handle); + printf("\twidth : %i\n", fb->width); + printf("\theight : %i\n", fb->height); + printf("\tpitch : %i\n", fb->pitch);; + printf("\tbpp : %i\n", fb->bpp); + printf("\tdepth : %i\n", fb->depth); + printf("\tbuffer_id : %i\n", fb->handle); + + return 0; +} + +int printRes(int fd, drmModeResPtr res) +{ + int i; + drmModeFBPtr fb; + drmModeCrtcPtr crtc; + drmModeEncoderPtr encoder; + drmModeConnectorPtr connector; + + printf("Resources\n\n"); + + printf("count_connectors : %i\n", res->count_connectors); + printf("count_encoders : %i\n", res->count_encoders); + printf("count_crtcs : %i\n", res->count_crtcs); + printf("count_fbs : %i\n", res->count_fbs); + + printf("\n"); + + if (connectors) { + for (i = 0; i < res->count_connectors; i++) { + connector = drmModeGetConnector(fd, res->connectors[i]); + + if (!connector) + printf("Could not get connector %i\n", res->connectors[i]); + else { + printConnector(fd, res, connector, res->connectors[i]); + drmModeFreeConnector(connector); + } + } + printf("\n"); + } + + + if (encoders) { + for (i = 0; i < res->count_encoders; i++) { + encoder = drmModeGetEncoder(fd, res->encoders[i]); + + if (!encoder) + printf("Could not get encoder %i\n", res->encoders[i]); + else { + printEncoder(fd, res, encoder, res->encoders[i]); + drmModeFreeEncoder(encoder); + } + } + printf("\n"); + } + + if (crtcs) { + for (i = 0; i < res->count_crtcs; i++) { + crtc = drmModeGetCrtc(fd, res->crtcs[i]); + + if (!crtc) + printf("Could not get crtc %i\n", res->crtcs[i]); + else { + printCrtc(fd, res, crtc, res->crtcs[i]); + drmModeFreeCrtc(crtc); + } + } + printf("\n"); + } + + if (fbs) { + for (i = 0; i < res->count_fbs; i++) { + fb = drmModeGetFB(fd, res->fbs[i]); + + if (!fb) + printf("Could not get fb %i\n", res->fbs[i]); + else { + printFrameBuffer(fd, res, fb); + drmModeFreeFB(fb); + } + } + } + + return 0; +} + +void args(int argc, char **argv) +{ + int i; + + fbs = 0; + edid = 0; + crtcs = 0; + modes = 0; + encoders = 0; + full_modes = 0; + full_props = 0; + connectors = 0; + + module_name = argv[1]; + + for (i = 2; i < argc; i++) { + if (strcmp(argv[i], "-fb") == 0) { + fbs = 1; + } else if (strcmp(argv[i], "-crtcs") == 0) { + crtcs = 1; + } else if (strcmp(argv[i], "-cons") == 0) { + connectors = 1; + modes = 1; + } else if (strcmp(argv[i], "-modes") == 0) { + connectors = 1; + modes = 1; + } else if (strcmp(argv[i], "-full") == 0) { + connectors = 1; + modes = 1; + full_modes = 1; + } else if (strcmp(argv[i], "-props") == 0) { + connectors = 1; + full_props = 1; + } else if (strcmp(argv[i], "-edids") == 0) { + connectors = 1; + edid = 1; + } else if (strcmp(argv[i], "-encoders") == 0) { + encoders = 1; + } else if (strcmp(argv[i], "-v") == 0) { + fbs = 1; + edid = 1; + crtcs = 1; + modes = 1; + encoders = 1; + full_modes = 1; + full_props = 1; + connectors = 1; + } + } + + if (argc == 2) { + fbs = 1; + edid = 1; + crtcs = 1; + modes = 1; + encoders = 1; + full_modes = 0; + full_props = 0; + connectors = 1; + } +} + +int main(int argc, char **argv) +{ + int fd; + drmModeResPtr res; + + if (argc == 1) { + printf("Please add modulename as first argument\n"); + return 1; + } + + args(argc, argv); + + printf("Starting test\n"); + + fd = drmOpen(module_name, NULL); + + if (fd < 0) { + printf("Failed to open the card fd (%d)\n",fd); + return 1; + } + + res = drmModeGetResources(fd); + if (res == 0) { + printf("Failed to get resources from card\n"); + drmClose(fd); + return 1; + } + + printRes(fd, res); + + drmModeFreeResources(res); + + printf("Ok\n"); + + return 0; +} diff --git a/tests/modeprint/test b/tests/modeprint/test new file mode 100644 index 00000000..bd1952cc --- /dev/null +++ b/tests/modeprint/test @@ -0,0 +1 @@ +LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@ diff --git a/tests/modetest/Makefile b/tests/modetest/Makefile new file mode 100644 index 00000000..8583ae82 --- /dev/null +++ b/tests/modetest/Makefile @@ -0,0 +1,14 @@ + +all: app + +#CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \ +# -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \ + +app: modetest.c + gcc $(CFLAGS) -o app -Wall -I../../libdrm -I../../libdrm/intel -I../../shared-core -L../../libdrm/.libs -L../../libdrm/intel/.libs -ldrm -ldrm_intel modetest.c + +clean: + @rm -f app + +run: app + sudo ./test diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c new file mode 100644 index 00000000..e5a16e1a --- /dev/null +++ b/tests/modetest/modetest.c @@ -0,0 +1,449 @@ +/* + * DRM based mode setting test program + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz + * Copyright 2008 Intel Corporation + * Jesse Barnes + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* + * This fairly simple test program dumps output in a similar format to the + * "xrandr" tool everyone knows & loves. It's necessarily slightly different + * since the kernel separates outputs into encoder and connector structures, + * each with their own unique ID. The program also allows test testing of the + * memory management and mode setting APIs by allowing the user to specify a + * connector and mode to use for mode setting. If all works as expected, a + * blue background should be painted on the monitor attached to the specified + * connector after the selected mode is set. + * + * TODO: use cairo to write the mode info on the selected output once + * the mode has been programmed, along with possible test patterns. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "xf86drm.h" +#include "xf86drmMode.h" +#include "intel_bufmgr.h" + +drmModeRes *resources; +int fd, modes; + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +struct type_name { + int type; + char *name; +}; + +#define type_name_fn(res) \ +char * res##_str(int type) { \ + int i; \ + for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \ + if (res##_names[i].type == type) \ + return res##_names[i].name; \ + } \ + return "(invalid)"; \ +} + +struct type_name encoder_type_names[] = { + { DRM_MODE_ENCODER_NONE, "none" }, + { DRM_MODE_ENCODER_DAC, "DAC" }, + { DRM_MODE_ENCODER_TMDS, "TMDS" }, + { DRM_MODE_ENCODER_LVDS, "LVDS" }, + { DRM_MODE_ENCODER_TVDAC, "TVDAC" }, +}; + +type_name_fn(encoder_type) + +struct type_name connector_status_names[] = { + { DRM_MODE_CONNECTED, "connected" }, + { DRM_MODE_DISCONNECTED, "disconnected" }, + { DRM_MODE_UNKNOWNCONNECTION, "unknown" }, +}; + +type_name_fn(connector_status) + +struct type_name connector_type_names[] = { + { DRM_MODE_CONNECTOR_Unknown, "unknown" }, + { DRM_MODE_CONNECTOR_VGA, "VGA" }, + { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, + { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, + { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, + { DRM_MODE_CONNECTOR_Composite, "composite" }, + { DRM_MODE_CONNECTOR_SVIDEO, "s-video" }, + { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, + { DRM_MODE_CONNECTOR_Component, "component" }, + { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, + { DRM_MODE_CONNECTOR_DisplayPort, "displayport" }, + { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, + { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, +}; + +type_name_fn(connector_type) + +void dump_encoders(void) +{ + drmModeEncoder *encoder; + int i; + + printf("Encoders:\n"); + printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n"); + for (i = 0; i < resources->count_encoders; i++) { + encoder = drmModeGetEncoder(fd, resources->encoders[i]); + + if (!encoder) { + fprintf(stderr, "could not get encoder %i: %s\n", + resources->encoders[i], strerror(errno)); + continue; + } + printf("%d\t%d\t%s\t0x%08x\t0x%08x\n", + encoder->encoder_id, + encoder->crtc_id, + encoder_type_str(encoder->encoder_type), + encoder->possible_crtcs, + encoder->possible_clones); + drmModeFreeEncoder(encoder); + } +} + +void dump_connectors(void) +{ + drmModeConnector *connector; + int i, j; + + printf("Connectors:\n"); + printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n"); + for (i = 0; i < resources->count_connectors; i++) { + 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++) { + struct drm_mode_modeinfo *mode; + + mode = &connector->modes[j]; + printf(" %s %.02f %d %d %d %d %d %d %d %d\n", + mode->name, + (float)mode->vrefresh / 1000, + mode->hdisplay, + mode->hsync_start, + mode->hsync_end, + mode->htotal, + mode->vdisplay, + mode->vsync_start, + mode->vsync_end, + mode->vtotal); + } + drmModeFreeConnector(connector); + } +} + +void dump_crtcs(void) +{ + drmModeCrtc *crtc; + int i; + + for (i = 0; i < resources->count_crtcs; i++) { + crtc = drmModeGetCrtc(fd, resources->crtcs[i]); + + if (!crtc) { + fprintf(stderr, "could not get crtc %i: %s\n", + resources->crtcs[i], strerror(errno)); + continue; + } + drmModeFreeCrtc(crtc); + } +} + +void dump_framebuffers(void) +{ + drmModeFB *fb; + int i; + + for (i = 0; i < resources->count_fbs; i++) { + fb = drmModeGetFB(fd, resources->fbs[i]); + + if (!fb) { + fprintf(stderr, "could not get fb %i: %s\n", + resources->fbs[i], strerror(errno)); + continue; + } + drmModeFreeFB(fb); + } +} + +/* + * Mode setting with the kernel interfaces is a bit of a chore. + * First you have to find the connector in question and make sure the + * requested mode is available. + * 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) +{ + 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 */ + for (i = 0; i < resources->count_connectors; i++) { + connector = drmModeGetConnector(fd, resources->connectors[i]); + + if (!connector) { + fprintf(stderr, "could not get connector %i: %s\n", + resources->connectors[i], strerror(errno)); + drmModeFreeConnector(connector); + continue; + } + + if (!connector->count_modes) { + drmModeFreeConnector(connector); + continue; + } + + if (connector->connector_id != connector_id) { + drmModeFreeConnector(connector); + continue; + } + + for (j = 0; j < connector->count_modes; j++) { + mode = &connector->modes[j]; + if (!strcmp(mode->name, mode_str)) + break; + } + + /* Found it, break out */ + if (mode) + break; + + drmModeFreeConnector(connector); + } + + if (!mode) { + fprintf(stderr, "failed to find mode \"%s\"\n", 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]); + + if (!encoder) { + fprintf(stderr, "could not get encoder %i: %s\n", + resources->encoders[i], strerror(errno)); + drmModeFreeEncoder(encoder); + continue; + } + + if (encoder->encoder_id == connector->encoder_id) + break; + + drmModeFreeEncoder(encoder); + } + + bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20); + if (!bufmgr) { + fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno)); + return; + } + + /* Mode size at 32 bpp */ + size = width * height * 4; + + bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096); + if (!bo) { + fprintf(stderr, "failed to alloc buffer: %s\n", + strerror(errno)); + return; + } + + ret = drm_intel_bo_pin(bo, 4096); + if (ret) { + fprintf(stderr, "failed to pin buffer: %s\n", strerror(errno)); + return; + } + + ret = drm_intel_gem_bo_map_gtt(bo); + if (ret) { + fprintf(stderr, "failed to GTT map buffer: %s\n", + strerror(errno)); + return; + } + + fb_ptr = bo->virtual; + + /* paint the buffer blue */ + for (i = 0; i < width * height; i++) + fb_ptr[i] = 0xff; + + ret = drmModeAddFB(fd, width, height, 32, 32, width * 4, 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; + } +} + +extern char *optarg; +extern int optind, opterr, optopt; +static char optstr[] = "ecpmfs:"; + +void usage(char *name) +{ + fprintf(stderr, "usage: %s [-ecpmf]\n", name); + fprintf(stderr, "\t-e\tlist encoders\n"); + fprintf(stderr, "\t-c\tlist connectors\n"); + 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-s :\tset a mode\n"); + fprintf(stderr, "\n\tDefault is to dump all info.\n"); + exit(0); +} + +#define dump_resource(res) if (res) dump_##res() + +int main(int argc, char **argv) +{ + int c; + int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0; + char *modules[] = { "i915", "radeon" }; + char *modeset = NULL, *mode, *connector; + int i, connector_id; + + opterr = 0; + while ((c = getopt(argc, argv, optstr)) != -1) { + switch (c) { + case 'e': + encoders = 1; + break; + case 'c': + connectors = 1; + break; + case 'p': + crtcs = 1; + break; + case 'm': + modes = 1; + break; + case 'f': + framebuffers = 1; + break; + case 's': + modeset = strdup(optarg); + break; + default: + usage(argv[0]); + break; + } + } + + if (argc == 1) + encoders = connectors = crtcs = modes = framebuffers = 1; + + for (i = 0; i < ARRAY_SIZE(modules); i++) { + printf("trying to load module %s...", modules[i]); + fd = drmOpen(modules[i], NULL); + if (fd < 0) { + printf("failed.\n"); + } else { + printf("success.\n"); + break; + } + } + + if (i == ARRAY_SIZE(modules)) { + fprintf(stderr, "failed to load any modules, aborting.\n"); + return -1; + } + + resources = drmModeGetResources(fd); + if (!resources) { + fprintf(stderr, "drmModeGetResources failed: %s\n", + strerror(errno)); + drmClose(fd); + return 1; + } + + dump_resource(encoders); + dump_resource(connectors); + 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); + } + + sleep(3); + + drmModeFreeResources(resources); + + return 0; +} diff --git a/tests/modetest/test b/tests/modetest/test new file mode 100644 index 00000000..5bb552ef --- /dev/null +++ b/tests/modetest/test @@ -0,0 +1,2 @@ +export LD_LIBRARY_PATH=../../libdrm/.libs:../../libdrm/intel/.libs +LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@ -- cgit v1.2.3