diff options
| author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-12-17 10:09:49 -0800 | 
|---|---|---|
| committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-12-17 10:11:37 -0800 | 
| commit | 731cd5526e5c732d51307b26e784f454a724a699 (patch) | |
| tree | 215249e4aa86a3d8418b7f5cad95551d49ecce2d /tests | |
| parent | c86d431fe6174b1c2de531929213ea7dbd92326d (diff) | |
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.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/Makefile.am | 4 | ||||
| -rw-r--r-- | tests/dristat.c | 2 | ||||
| -rw-r--r-- | tests/modeprint/Makefile | 14 | ||||
| -rwxr-xr-x | tests/modeprint/app | bin | 0 -> 16233 bytes | |||
| -rw-r--r-- | tests/modeprint/modeprint.c | 402 | ||||
| -rw-r--r-- | tests/modeprint/test | 1 | ||||
| -rw-r--r-- | tests/modetest/Makefile | 14 | ||||
| -rw-r--r-- | tests/modetest/modetest.c | 449 | ||||
| -rw-r--r-- | tests/modetest/test | 2 | 
9 files changed, 887 insertions, 1 deletions
| 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/appBinary files differ new file mode 100755 index 00000000..82085c85 --- /dev/null +++ b/tests/modeprint/app 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 <wallbraker@gmail.com> + */ + +/* + * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com> + * + * 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 <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> + +#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 <jakob@tungstengraphics.com> + * Copyright 2008 Intel Corporation + *   Jesse Barnes <jesse.barnes@intel.com> + * + * 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 <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#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 <connector_id>:<mode>\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 $@ | 
