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.
main
Jesse Barnes 2008-12-17 10:09:49 -08:00
parent c86d431fe6
commit 731cd5526e
20 changed files with 2179 additions and 12 deletions

View File

@ -26,9 +26,10 @@ libdrm_la_LDFLAGS = -version-number 2:4:0 -no-undefined
AM_CFLAGS = -I$(top_srcdir)/shared-core AM_CFLAGS = -I$(top_srcdir)/shared-core
libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c \ libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c \
xf86drmMode.c libdrm_lists.h
libdrm_lists.h libdrm_lists.h
libdrmincludedir = ${includedir} libdrmincludedir = ${includedir}
libdrminclude_HEADERS = xf86drm.h libdrminclude_HEADERS = xf86drm.h xf86drmMode.h
EXTRA_DIST = ChangeLog TODO EXTRA_DIST = ChangeLog TODO

View File

@ -66,6 +66,11 @@ struct _drm_intel_bo {
/** Buffer manager context associated with this buffer object */ /** Buffer manager context associated with this buffer object */
drm_intel_bufmgr *bufmgr; drm_intel_bufmgr *bufmgr;
/**
* MM-specific handle for accessing object
*/
int handle;
}; };
drm_intel_bo *drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name, drm_intel_bo *drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,

View File

@ -351,6 +351,7 @@ drm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CREATE, &create); ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
bo_gem->gem_handle = create.handle; bo_gem->gem_handle = create.handle;
bo_gem->bo.handle = bo_gem->gem_handle;
if (ret != 0) { if (ret != 0) {
free(bo_gem); free(bo_gem);
return NULL; return NULL;

View File

@ -87,6 +87,9 @@
#define DRM_MSG_VERBOSITY 3 #define DRM_MSG_VERBOSITY 3
#define DRM_NODE_CONTROL 0
#define DRM_NODE_RENDER 1
static drmServerInfoPtr drm_server_info; static drmServerInfoPtr drm_server_info;
void drmSetServerInfo(drmServerInfoPtr info) void drmSetServerInfo(drmServerInfoPtr info)
@ -174,7 +177,7 @@ static char *drmStrdup(const char *s)
/** /**
* Call ioctl, restarting if it is interupted * Call ioctl, restarting if it is interupted
*/ */
static int int
drmIoctl(int fd, unsigned long request, void *arg) drmIoctl(int fd, unsigned long request, void *arg)
{ {
int ret; int ret;
@ -277,7 +280,7 @@ static int drmMatchBusID(const char *id1, const char *id2)
* special file node with the major and minor numbers specified by \p dev and * special file node with the major and minor numbers specified by \p dev and
* parent directory if necessary and was called by root. * parent directory if necessary and was called by root.
*/ */
static int drmOpenDevice(long dev, int minor) static int drmOpenDevice(long dev, int minor, int type)
{ {
stat_t st; stat_t st;
char buf[64]; char buf[64];
@ -287,7 +290,7 @@ static int drmOpenDevice(long dev, int minor)
uid_t user = DRM_DEV_UID; uid_t user = DRM_DEV_UID;
gid_t group = DRM_DEV_GID, serv_group; gid_t group = DRM_DEV_GID, serv_group;
sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
drmMsg("drmOpenDevice: node name is %s\n", buf); drmMsg("drmOpenDevice: node name is %s\n", buf);
if (drm_server_info) { if (drm_server_info) {
@ -386,15 +389,15 @@ wait_for_udev:
* Calls drmOpenDevice() if \p create is set, otherwise assembles the device * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
* name from \p minor and opens it. * name from \p minor and opens it.
*/ */
static int drmOpenMinor(int minor, int create) static int drmOpenMinor(int minor, int create, int type)
{ {
int fd; int fd;
char buf[64]; char buf[64];
if (create) if (create)
return drmOpenDevice(makedev(DRM_MAJOR, minor), minor); return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
if ((fd = open(buf, O_RDWR, 0)) >= 0) if ((fd = open(buf, O_RDWR, 0)) >= 0)
return fd; return fd;
return -errno; return -errno;
@ -417,7 +420,7 @@ int drmAvailable(void)
int retval = 0; int retval = 0;
int fd; int fd;
if ((fd = drmOpenMinor(0, 1)) < 0) { if ((fd = drmOpenMinor(0, 1, DRM_NODE_RENDER)) < 0) {
#ifdef __linux__ #ifdef __linux__
/* Try proc for backward Linux compatibility */ /* Try proc for backward Linux compatibility */
if (!access("/proc/dri/0", R_OK)) if (!access("/proc/dri/0", R_OK))
@ -458,7 +461,7 @@ static int drmOpenByBusid(const char *busid)
drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid); drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
for (i = 0; i < DRM_MAX_MINOR; i++) { for (i = 0; i < DRM_MAX_MINOR; i++) {
fd = drmOpenMinor(i, 1); fd = drmOpenMinor(i, 1, DRM_NODE_RENDER);
drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd); drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
if (fd >= 0) { if (fd >= 0) {
sv.drm_di_major = 1; sv.drm_di_major = 1;
@ -520,7 +523,7 @@ static int drmOpenByName(const char *name)
* already in use. If it's in use it will have a busid assigned already. * already in use. If it's in use it will have a busid assigned already.
*/ */
for (i = 0; i < DRM_MAX_MINOR; i++) { for (i = 0; i < DRM_MAX_MINOR; i++) {
if ((fd = drmOpenMinor(i, 1)) >= 0) { if ((fd = drmOpenMinor(i, 1, DRM_NODE_RENDER)) >= 0) {
if ((version = drmGetVersion(fd))) { if ((version = drmGetVersion(fd))) {
if (!strcmp(version->name, name)) { if (!strcmp(version->name, name)) {
drmFreeVersion(version); drmFreeVersion(version);
@ -564,7 +567,7 @@ static int drmOpenByName(const char *name)
if (*pt) { /* Found busid */ if (*pt) { /* Found busid */
return drmOpenByBusid(++pt); return drmOpenByBusid(++pt);
} else { /* No busid */ } else { /* No busid */
return drmOpenDevice(strtol(devstring, NULL, 0),i); return drmOpenDevice(strtol(devstring, NULL, 0),i, DRM_NODE_RENDER);
} }
} }
} }
@ -614,6 +617,10 @@ int drmOpen(const char *name, const char *busid)
return -1; return -1;
} }
int drmOpenControl(int minor)
{
return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
}
/** /**
* Free the version information returned by drmGetVersion(). * Free the version information returned by drmGetVersion().
@ -2434,3 +2441,20 @@ void drmCloseOnce(int fd)
} }
} }
} }
int drmSetMaster(int fd)
{
int ret;
fprintf(stderr,"Setting master \n");
ret = ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
return ret;
}
int drmDropMaster(int fd)
{
int ret;
fprintf(stderr,"Dropping master \n");
ret = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
return ret;
}

View File

@ -49,6 +49,7 @@
#define DRM_DIR_NAME "/dev/dri" #define DRM_DIR_NAME "/dev/dri"
#define DRM_DEV_NAME "%s/card%d" #define DRM_DEV_NAME "%s/card%d"
#define DRM_CONTROL_DEV_NAME "%s/controlD%d"
#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */ #define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
#define DRM_ERR_NO_DEVICE (-1001) #define DRM_ERR_NO_DEVICE (-1001)
@ -74,6 +75,7 @@ typedef struct drmHashEntry {
void *tagTable; void *tagTable;
} drmHashEntry; } drmHashEntry;
extern int drmIoctl(int fd, unsigned long request, void *arg);
extern void *drmGetHashTable(void); extern void *drmGetHashTable(void);
extern drmHashEntry *drmGetEntry(int fd); extern drmHashEntry *drmGetEntry(int fd);
@ -508,6 +510,7 @@ do { register unsigned int __old __asm("o0"); \
/* General user-level programmer's API: unprivileged */ /* General user-level programmer's API: unprivileged */
extern int drmAvailable(void); extern int drmAvailable(void);
extern int drmOpen(const char *name, const char *busid); extern int drmOpen(const char *name, const char *busid);
extern int drmOpenControl(int minor);
extern int drmClose(int fd); extern int drmClose(int fd);
extern drmVersionPtr drmGetVersion(int fd); extern drmVersionPtr drmGetVersion(int fd);
extern drmVersionPtr drmGetLibVersion(int fd); extern drmVersionPtr drmGetLibVersion(int fd);
@ -659,4 +662,7 @@ extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened);
extern void drmCloseOnce(int fd); extern void drmCloseOnce(int fd);
extern void drmMsg(const char *format, ...); extern void drmMsg(const char *format, ...);
extern int drmSetMaster(int fd);
extern int drmDropMaster(int fd);
#endif #endif

686
libdrm/xf86drmMode.c Normal file
View File

@ -0,0 +1,686 @@
/*
* \file xf86drmMode.c
* Header for DRM modesetting interface.
*
* \author Jakob Bornecrantz <wallbraker@gmail.com>
*
* \par Acknowledgements:
* Feb 2007, Dave Airlie <airlied@linux.ie>
*/
/*
* Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie>
* 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.
*
*/
/*
* TODO the types we are after are defined in diffrent headers on diffrent
* platforms find which headers to include to get uint32_t
*/
#include <stdint.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include "xf86drmMode.h"
#include "xf86drm.h"
#include <drm.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#define U642VOID(x) ((void *)(unsigned long)(x))
#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
/*
* Util functions
*/
void* drmAllocCpy(void *array, int count, int entry_size)
{
char *r;
int i;
if (!count || !array || !entry_size)
return 0;
if (!(r = drmMalloc(count*entry_size)))
return 0;
for (i = 0; i < count; i++)
memcpy(r+(entry_size*i), array+(entry_size*i), entry_size);
return r;
}
/*
* A couple of free functions.
*/
void drmModeFreeModeInfo(struct drm_mode_modeinfo *ptr)
{
if (!ptr)
return;
drmFree(ptr);
}
void drmModeFreeResources(drmModeResPtr ptr)
{
if (!ptr)
return;
drmFree(ptr);
}
void drmModeFreeFB(drmModeFBPtr ptr)
{
if (!ptr)
return;
/* we might add more frees later. */
drmFree(ptr);
}
void drmModeFreeCrtc(drmModeCrtcPtr ptr)
{
if (!ptr)
return;
drmFree(ptr);
}
void drmModeFreeConnector(drmModeConnectorPtr ptr)
{
if (!ptr)
return;
drmFree(ptr->modes);
drmFree(ptr);
}
void drmModeFreeEncoder(drmModeEncoderPtr ptr)
{
drmFree(ptr);
}
/*
* ModeSetting functions.
*/
drmModeResPtr drmModeGetResources(int fd)
{
struct drm_mode_card_res res;
drmModeResPtr r = 0;
memset(&res, 0, sizeof(struct drm_mode_card_res));
if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
return 0;
if (res.count_fbs)
res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t)));
if (res.count_crtcs)
res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t)));
if (res.count_connectors)
res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t)));
if (res.count_encoders)
res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t)));
if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) {
r = NULL;
goto err_allocs;
}
/*
* return
*/
if (!(r = drmMalloc(sizeof(*r))))
return 0;
r->min_width = res.min_width;
r->max_width = res.max_width;
r->min_height = res.min_height;
r->max_height = res.max_height;
r->count_fbs = res.count_fbs;
r->count_crtcs = res.count_crtcs;
r->count_connectors = res.count_connectors;
r->count_encoders = res.count_encoders;
/* TODO we realy should test if these allocs fails. */
r->fbs = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t));
r->crtcs = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t));
r->encoders = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t));
err_allocs:
drmFree(U642VOID(res.fb_id_ptr));
drmFree(U642VOID(res.crtc_id_ptr));
drmFree(U642VOID(res.connector_id_ptr));
drmFree(U642VOID(res.encoder_id_ptr));
return r;
}
int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
uint32_t *buf_id)
{
struct drm_mode_fb_cmd f;
int ret;
f.width = width;
f.height = height;
f.pitch = pitch;
f.bpp = bpp;
f.depth = depth;
f.handle = bo_handle;
if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &f)))
return ret;
*buf_id = f.fb_id;
return 0;
}
int drmModeRmFB(int fd, uint32_t bufferId)
{
return drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
}
drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
{
struct drm_mode_fb_cmd info;
drmModeFBPtr r;
info.fb_id = buf;
if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info))
return NULL;
if (!(r = drmMalloc(sizeof(*r))))
return NULL;
r->fb_id = info.fb_id;
r->width = info.width;
r->height = info.height;
r->pitch = info.pitch;
r->bpp = info.bpp;
r->handle = info.handle;
r->depth = info.depth;
return r;
}
/*
* Crtc functions
*/
drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
{
struct drm_mode_crtc crtc;
drmModeCrtcPtr r;
crtc.crtc_id = crtcId;
if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
return 0;
/*
* return
*/
if (!(r = drmMalloc(sizeof(*r))))
return 0;
r->crtc_id = crtc.crtc_id;
r->x = crtc.x;
r->y = crtc.y;
r->mode_valid = crtc.mode_valid;
if (r->mode_valid)
memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
r->buffer_id = crtc.fb_id;
r->gamma_size = crtc.gamma_size;
return r;
}
int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t *connectors, int count,
struct drm_mode_modeinfo *mode)
{
struct drm_mode_crtc crtc;
crtc.x = x;
crtc.y = y;
crtc.crtc_id = crtcId;
crtc.fb_id = bufferId;
crtc.set_connectors_ptr = VOID2U64(connectors);
crtc.count_connectors = count;
if (mode) {
memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
crtc.mode_valid = 1;
} else
crtc.mode_valid = 0;
return drmIoctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
}
/*
* Cursor manipulation
*/
int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height)
{
struct drm_mode_cursor arg;
arg.flags = DRM_MODE_CURSOR_BO;
arg.crtc_id = crtcId;
arg.width = width;
arg.height = height;
arg.handle = bo_handle;
return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
}
int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
{
struct drm_mode_cursor arg;
arg.flags = DRM_MODE_CURSOR_MOVE;
arg.crtc_id = crtcId;
arg.x = x;
arg.y = y;
return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
}
/*
* Encoder get
*/
drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
{
struct drm_mode_get_encoder enc;
drmModeEncoderPtr r = NULL;
enc.encoder_id = encoder_id;
enc.encoder_type = 0;
enc.possible_crtcs = 0;
enc.possible_clones = 0;
if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))
return 0;
if (!(r = drmMalloc(sizeof(*r))))
return 0;
r->encoder_id = enc.encoder_id;
r->crtc_id = enc.crtc_id;
r->encoder_type = enc.encoder_type;
r->possible_crtcs = enc.possible_crtcs;
r->possible_clones = enc.possible_clones;
return r;
}
/*
* Connector manipulation
*/
drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
{
struct drm_mode_get_connector conn;
drmModeConnectorPtr r = NULL;
conn.connector_id = connector_id;
conn.connector_type_id = 0;
conn.connector_type = 0;
conn.count_modes = 0;
conn.modes_ptr = 0;
conn.count_props = 0;
conn.props_ptr = 0;
conn.prop_values_ptr = 0;
conn.count_encoders = 0;
conn.encoders_ptr = 0;
if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
return 0;
if (conn.count_props) {
conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
}
if (conn.count_modes)
conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
if (conn.count_encoders)
conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));
if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
goto err_allocs;
if(!(r = drmMalloc(sizeof(*r)))) {
goto err_allocs;
}
r->connector_id = conn.connector_id;
r->encoder_id = conn.encoder_id;
r->connection = conn.connection;
r->mmWidth = conn.mm_width;
r->mmHeight = conn.mm_height;
r->subpixel = conn.subpixel;
r->count_modes = conn.count_modes;
/* TODO we should test if these alloc & cpy fails. */
r->count_props = conn.count_props;
r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));
r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));
r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));
r->count_encoders = conn.count_encoders;
r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));
r->connector_type = conn.connector_type;
r->connector_type_id = conn.connector_type_id;
if (!r->props || !r->prop_values || !r->modes || !r->encoders)
goto err_allocs;
err_allocs:
drmFree(U642VOID(conn.prop_values_ptr));
drmFree(U642VOID(conn.props_ptr));
drmFree(U642VOID(conn.modes_ptr));
drmFree(U642VOID(conn.encoders_ptr));
return r;
}
int drmModeAttachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info)
{
struct drm_mode_mode_cmd res;
memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
res.connector_id = connector_id;
return drmIoctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
}
int drmModeDetachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info)
{
struct drm_mode_mode_cmd res;
memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
res.connector_id = connector_id;
return drmIoctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
}
drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
{
struct drm_mode_get_property prop;
drmModePropertyPtr r;
prop.prop_id = property_id;
prop.count_enum_blobs = 0;
prop.count_values = 0;
prop.flags = 0;
prop.enum_blob_ptr = 0;
prop.values_ptr = 0;
if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
return 0;
if (prop.count_values)
prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM))
prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
}
if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) {
r = NULL;
goto err_allocs;
}
if (!(r = drmMalloc(sizeof(*r))))
return NULL;
r->prop_id = prop.prop_id;
r->count_values = prop.count_values;
r->flags = prop.flags;
if (prop.count_values)
r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t));
if (prop.flags & DRM_MODE_PROP_ENUM) {
r->count_enums = prop.count_enum_blobs;
r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum));
} else if (prop.flags & DRM_MODE_PROP_BLOB) {
r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t));
r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t));
r->count_blobs = prop.count_enum_blobs;
}
strncpy(r->name, prop.name, DRM_PROP_NAME_LEN);
r->name[DRM_PROP_NAME_LEN-1] = 0;
err_allocs:
drmFree(U642VOID(prop.values_ptr));
drmFree(U642VOID(prop.enum_blob_ptr));
return r;
}
void drmModeFreeProperty(drmModePropertyPtr ptr)
{
if (!ptr)
return;
drmFree(ptr->values);
drmFree(ptr->enums);
drmFree(ptr);
}
drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
{
struct drm_mode_get_blob blob;
drmModePropertyBlobPtr r;
blob.length = 0;
blob.data = 0;
blob.blob_id = blob_id;
if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
return NULL;
if (blob.length)
blob.data = VOID2U64(drmMalloc(blob.length));
if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
r = NULL;
goto err_allocs;
}
if (!(r = drmMalloc(sizeof(*r))))
return NULL;
r->id = blob.blob_id;
r->length = blob.length;
r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length);
err_allocs:
drmFree(U642VOID(blob.data));
return r;
}
void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
{
if (!ptr)
return;
drmFree(ptr->data);
drmFree(ptr);
}
int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
uint64_t value)
{
struct drm_mode_connector_set_property osp;
int ret;
osp.connector_id = connector_id;
osp.prop_id = property_id;
osp.value = value;
if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)))
return ret;
return 0;
}
/*
* checks if a modesetting capable driver has attached to the pci id
* returns 0 if modesetting supported.
* -EINVAL or invalid bus id
* -ENOSYS if no modesetting support
*/
int drmCheckModesettingSupported(const char *busid)
{
#ifdef __linux__
char pci_dev_dir[1024];
int domain, bus, dev, func;
DIR *sysdir;
struct dirent *dent;
int found = 0, ret;
ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func);
if (ret != 4)
return -EINVAL;
sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm",
domain, bus, dev, func);
sysdir = opendir(pci_dev_dir);
if (sysdir) {
dent = readdir(sysdir);
while (dent) {
if (!strncmp(dent->d_name, "controlD", 8)) {
found = 1;
break;
}
dent = readdir(sysdir);
}
closedir(sysdir);
if (found)
return 0;
}
sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
domain, bus, dev, func);
sysdir = opendir(pci_dev_dir);
if (!sysdir)
return -EINVAL;
dent = readdir(sysdir);
while (dent) {
if (!strncmp(dent->d_name, "drm:controlD", 12)) {
found = 1;
break;
}
dent = readdir(sysdir);
}
closedir(sysdir);
if (found)
return 0;
#endif
return -ENOSYS;
}
int drmModeReplaceFB(int fd, uint32_t buffer_id,
uint32_t width, uint32_t height, uint8_t depth,
uint8_t bpp, uint32_t pitch, uint32_t bo_handle)
{
struct drm_mode_fb_cmd f;
int ret;
f.width = width;
f.height = height;
f.pitch = pitch;
f.bpp = bpp;
f.depth = depth;
f.handle = bo_handle;
f.fb_id = buffer_id;
if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_REPLACEFB, &f)))
return ret;
return 0;
}
int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
uint16_t *red, uint16_t *green, uint16_t *blue)
{
int ret;
struct drm_mode_crtc_lut l;
l.crtc_id = crtc_id;
l.gamma_size = size;
l.red = VOID2U64(red);
l.green = VOID2U64(green);
l.blue = VOID2U64(blue);
if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_GETGAMMA, &l)))
return ret;
return 0;
}
int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
uint16_t *red, uint16_t *green, uint16_t *blue)
{
int ret;
struct drm_mode_crtc_lut l;
l.crtc_id = crtc_id;
l.gamma_size = size;
l.red = VOID2U64(red);
l.green = VOID2U64(green);
l.blue = VOID2U64(blue);
if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETGAMMA, &l)))
return ret;
return 0;
}

258
libdrm/xf86drmMode.h Normal file
View File

@ -0,0 +1,258 @@
/*
* \file xf86drmMode.h
* Header for DRM modesetting interface.
*
* \author Jakob Bornecrantz <wallbraker@gmail.com>
*
* \par Acknowledgements:
* Feb 2007, Dave Airlie <airlied@linux.ie>
*/
/*
* Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie>
* 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 <drm.h>
/*
* This is the interface for modesetting for drm.
*
* In order to use this interface you must include either <stdint.h> or another
* header defining uint32_t, int32_t and uint16_t.
*
* It aims to provide a randr1.2 compatible interface for modesettings in the
* kernel, the interface is also ment to be used by libraries like EGL.
*
* More information can be found in randrproto.txt which can be found here:
* http://gitweb.freedesktop.org/?p=xorg/proto/randrproto.git
*
* There are some major diffrences to be noted. Unlike the randr1.2 proto you
* need to create the memory object of the framebuffer yourself with the ttm
* buffer object interface. This object needs to be pinned.
*/
typedef struct _drmModeRes {
int count_fbs;
uint32_t *fbs;
int count_crtcs;
uint32_t *crtcs;
int count_connectors;
uint32_t *connectors;
int count_encoders;
uint32_t *encoders;
uint32_t min_width, max_width;
uint32_t min_height, max_height;
} drmModeRes, *drmModeResPtr;
typedef struct drm_mode_fb_cmd drmModeFB, *drmModeFBPtr;
typedef struct _drmModePropertyBlob {
uint32_t id;
uint32_t length;
void *data;
} drmModePropertyBlobRes, *drmModePropertyBlobPtr;
typedef struct _drmModeProperty {
uint32_t prop_id;
uint32_t flags;
char name[DRM_PROP_NAME_LEN];
int count_values;
uint64_t *values; // store the blob lengths
int count_enums;
struct drm_mode_property_enum *enums;
int count_blobs;
uint32_t *blob_ids; // store the blob IDs
} drmModePropertyRes, *drmModePropertyPtr;
typedef struct _drmModeCrtc {
uint32_t crtc_id;
uint32_t buffer_id; /**< FB id to connect to 0 = disconnect */
uint32_t x, y; /**< Position on the framebuffer */
uint32_t width, height;
int mode_valid;
struct drm_mode_modeinfo mode;
int gamma_size; /**< Number of gamma stops */
} drmModeCrtc, *drmModeCrtcPtr;
typedef struct _drmModeEncoder {
uint32_t encoder_id;
uint32_t encoder_type;
uint32_t crtc_id;
uint32_t possible_crtcs;
uint32_t possible_clones;
} drmModeEncoder, *drmModeEncoderPtr;
typedef enum {
DRM_MODE_CONNECTED = 1,
DRM_MODE_DISCONNECTED = 2,
DRM_MODE_UNKNOWNCONNECTION = 3
} drmModeConnection;
typedef enum {
DRM_MODE_SUBPIXEL_UNKNOWN = 1,
DRM_MODE_SUBPIXEL_HORIZONTAL_RGB = 2,
DRM_MODE_SUBPIXEL_HORIZONTAL_BGR = 3,
DRM_MODE_SUBPIXEL_VERTICAL_RGB = 4,
DRM_MODE_SUBPIXEL_VERTICAL_BGR = 5,
DRM_MODE_SUBPIXEL_NONE = 6
} drmModeSubPixel;
typedef struct _drmModeConnector {
uint32_t connector_id;
uint32_t encoder_id; /**< Encoder currently connected to */
uint32_t connector_type;
uint32_t connector_type_id;
drmModeConnection connection;
uint32_t mmWidth, mmHeight; /**< HxW in millimeters */
drmModeSubPixel subpixel;
int count_modes;
struct drm_mode_modeinfo *modes;
int count_props;
uint32_t *props; /**< List of property ids */
uint64_t *prop_values; /**< List of property values */
int count_encoders;
uint32_t *encoders; /**< List of encoder ids */
} drmModeConnector, *drmModeConnectorPtr;
extern void drmModeFreeModeInfo( struct drm_mode_modeinfo *ptr );
extern void drmModeFreeResources( drmModeResPtr ptr );
extern void drmModeFreeFB( drmModeFBPtr ptr );
extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
/**
* Retrives all of the resources associated with a card.
*/
extern drmModeResPtr drmModeGetResources(int fd);
/*
* FrameBuffer manipulation.
*/
/**
* Retrive information about framebuffer bufferId
*/
extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
/**
* Creates a new framebuffer with an buffer object as its scanout buffer.
*/
extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
uint32_t *buf_id);
/**
* Destroies the given framebuffer.
*/
extern int drmModeRmFB(int fd, uint32_t bufferId);
/**
* Replace a framebuffer object with a new one - for resizing the screen.
*/
extern int drmModeReplaceFB(int fd, uint32_t buffer_id,
uint32_t width, uint32_t height, uint8_t depth,
uint8_t bpp, uint32_t pitch, uint32_t bo_handle);
/*
* Crtc functions
*/
/**
* Retrive information about the ctrt crtcId
*/
extern drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId);
/**
* Set the mode on a crtc crtcId with the given mode modeId.
*/
int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t *connectors, int count,
struct drm_mode_modeinfo *mode);
/*
* Cursor functions
*/
/**
* Set the cursor on crtc
*/
int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height);
/**
* Move the cursor on crtc
*/
int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y);
/**
* Encoder functions
*/
drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id);
/*
* Connector manipulation
*/
/**
* Retrive information about the connector connectorId.
*/
extern drmModeConnectorPtr drmModeGetConnector(int fd,
uint32_t connectorId);
/**
* Attaches the given mode to an connector.
*/
extern int drmModeAttachMode(int fd, uint32_t connectorId, struct drm_mode_modeinfo *mode_info);
/**
* Detaches a mode from the connector
* must be unused, by the given mode.
*/
extern int drmModeDetachMode(int fd, uint32_t connectorId, struct drm_mode_modeinfo *mode_info);
extern drmModePropertyPtr drmModeGetProperty(int fd, uint32_t propertyId);
extern void drmModeFreeProperty(drmModePropertyPtr ptr);
extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id);
extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr);
extern int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
uint64_t value);
extern int drmCheckModesettingSupported(const char *busid);
extern int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
uint16_t *red, uint16_t *green, uint16_t *blue);
extern int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
uint16_t *red, uint16_t *green, uint16_t *blue);

1
linux-core/drm_mode.h Symbolic link
View File

@ -0,0 +1 @@
../shared-core/drm_mode.h

View File

@ -25,6 +25,7 @@
klibdrmincludedir = ${includedir}/drm klibdrmincludedir = ${includedir}/drm
klibdrminclude_HEADERS = \ klibdrminclude_HEADERS = \
drm.h \ drm.h \
drm_mode.h \
drm_sarea.h \ drm_sarea.h \
i915_drm.h \ i915_drm.h \
mach64_drm.h \ mach64_drm.h \

View File

@ -985,6 +985,8 @@ struct drm_gem_open {
uint64_t size; uint64_t size;
}; };
#include "drm_mode.h"
/** /**
* \name Ioctls Definitions * \name Ioctls Definitions
*/ */
@ -1027,6 +1029,9 @@ struct drm_gem_open {
#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) #define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map)
#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) #define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map)
#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e)
#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f)
#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) #define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx)
#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) #define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx)
#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) #define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx)
@ -1082,6 +1087,28 @@ struct drm_gem_open {
#define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg) #define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg)
#define DRM_IOCTL_MM_INFO DRM_IOWR(0xd7, struct drm_mm_info_arg) #define DRM_IOCTL_MM_INFO DRM_IOWR(0xd7, struct drm_mm_info_arg)
#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc)
#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor)
#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut)
#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut)
#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder)
#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector)
#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd)
#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd)
#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property)
#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property)
#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob)
#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, uint32_t)
#define DRM_IOCTL_MODE_REPLACEFB DRM_IOWR(0xB0, struct drm_mode_fb_cmd)
/*@}*/ /*@}*/
/** /**

271
shared-core/drm_mode.h Normal file
View File

@ -0,0 +1,271 @@
/*
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
* Copyright (c) 2007 Jakob Bornecrantz <wallbraker@gmail.com>
* Copyright (c) 2008 Red Hat Inc.
* Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
* Copyright (c) 2007-2008 Intel Corporation
*
* 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.
*/
#ifndef _DRM_MODE_H
#define _DRM_MODE_H
#if !defined(__KERNEL__) && !defined(_KERNEL)
#include <stdint.h>
#else
#include <linux/kernel.h>
#endif
#define DRM_DISPLAY_INFO_LEN 32
#define DRM_CONNECTOR_NAME_LEN 32
#define DRM_DISPLAY_MODE_LEN 32
#define DRM_PROP_NAME_LEN 32
#define DRM_MODE_TYPE_BUILTIN (1<<0)
#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN)
#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN)
#define DRM_MODE_TYPE_PREFERRED (1<<3)
#define DRM_MODE_TYPE_DEFAULT (1<<4)
#define DRM_MODE_TYPE_USERDEF (1<<5)
#define DRM_MODE_TYPE_DRIVER (1<<6)
/* Video mode flags */
/* bit compatible with the xorg definitions. */
#define DRM_MODE_FLAG_PHSYNC (1<<0)
#define DRM_MODE_FLAG_NHSYNC (1<<1)
#define DRM_MODE_FLAG_PVSYNC (1<<2)
#define DRM_MODE_FLAG_NVSYNC (1<<3)
#define DRM_MODE_FLAG_INTERLACE (1<<4)
#define DRM_MODE_FLAG_DBLSCAN (1<<5)
#define DRM_MODE_FLAG_CSYNC (1<<6)
#define DRM_MODE_FLAG_PCSYNC (1<<7)
#define DRM_MODE_FLAG_NCSYNC (1<<8)
#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */
#define DRM_MODE_FLAG_BCAST (1<<10)
#define DRM_MODE_FLAG_PIXMUX (1<<11)
#define DRM_MODE_FLAG_DBLCLK (1<<12)
#define DRM_MODE_FLAG_CLKDIV2 (1<<13)
/* DPMS flags */
/* bit compatible with the xorg definitions. */
#define DRM_MODE_DPMS_ON 0
#define DRM_MODE_DPMS_STANDBY 1
#define DRM_MODE_DPMS_SUSPEND 2
#define DRM_MODE_DPMS_OFF 3
/* Scaling mode options */
#define DRM_MODE_SCALE_NON_GPU 0
#define DRM_MODE_SCALE_FULLSCREEN 1
#define DRM_MODE_SCALE_NO_SCALE 2
#define DRM_MODE_SCALE_ASPECT 3
/* Dithering mode options */
#define DRM_MODE_DITHERING_OFF 0
#define DRM_MODE_DITHERING_ON 1
struct drm_mode_modeinfo {
uint32_t clock;
uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew;
uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan;
uint32_t vrefresh; /* vertical refresh * 1000 */
uint32_t flags;
uint32_t type;
char name[DRM_DISPLAY_MODE_LEN];
};
struct drm_mode_card_res {
uint64_t fb_id_ptr;
uint64_t crtc_id_ptr;
uint64_t connector_id_ptr;
uint64_t encoder_id_ptr;
uint32_t count_fbs;
uint32_t count_crtcs;
uint32_t count_connectors;
uint32_t count_encoders;
uint32_t min_width, max_width;
uint32_t min_height, max_height;
};
struct drm_mode_crtc {
uint64_t set_connectors_ptr;
uint32_t count_connectors;
uint32_t crtc_id; /**< Id */
uint32_t fb_id; /**< Id of framebuffer */
uint32_t x, y; /**< Position on the frameuffer */
uint32_t gamma_size;
uint32_t mode_valid;
struct drm_mode_modeinfo mode;
};
#define DRM_MODE_ENCODER_NONE 0
#define DRM_MODE_ENCODER_DAC 1
#define DRM_MODE_ENCODER_TMDS 2
#define DRM_MODE_ENCODER_LVDS 3
#define DRM_MODE_ENCODER_TVDAC 4
struct drm_mode_get_encoder {
uint32_t encoder_id;
uint32_t encoder_type;
uint32_t crtc_id; /**< Id of crtc */
uint32_t possible_crtcs;
uint32_t possible_clones;
};
/* This is for connectors with multiple signal types. */
/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */
#define DRM_MODE_SUBCONNECTOR_Automatic 0
#define DRM_MODE_SUBCONNECTOR_Unknown 0
#define DRM_MODE_SUBCONNECTOR_DVID 3
#define DRM_MODE_SUBCONNECTOR_DVIA 4
#define DRM_MODE_SUBCONNECTOR_Composite 5
#define DRM_MODE_SUBCONNECTOR_SVIDEO 6
#define DRM_MODE_SUBCONNECTOR_Component 8
#define DRM_MODE_CONNECTOR_Unknown 0
#define DRM_MODE_CONNECTOR_VGA 1
#define DRM_MODE_CONNECTOR_DVII 2
#define DRM_MODE_CONNECTOR_DVID 3
#define DRM_MODE_CONNECTOR_DVIA 4
#define DRM_MODE_CONNECTOR_Composite 5
#define DRM_MODE_CONNECTOR_SVIDEO 6
#define DRM_MODE_CONNECTOR_LVDS 7
#define DRM_MODE_CONNECTOR_Component 8
#define DRM_MODE_CONNECTOR_9PinDIN 9
#define DRM_MODE_CONNECTOR_DisplayPort 10
#define DRM_MODE_CONNECTOR_HDMIA 11
#define DRM_MODE_CONNECTOR_HDMIB 12
struct drm_mode_get_connector {
uint64_t encoders_ptr;
uint64_t modes_ptr;
uint64_t props_ptr;
uint64_t prop_values_ptr;
uint32_t count_modes;
uint32_t count_props;
uint32_t count_encoders;
uint32_t encoder_id; /**< Current Encoder */
uint32_t connector_id; /**< Id */
uint32_t connector_type;
uint32_t connector_type_id;
uint32_t connection;
uint32_t mm_width, mm_height; /**< HxW in millimeters */
uint32_t subpixel;
};
#define DRM_MODE_PROP_PENDING (1<<0)
#define DRM_MODE_PROP_RANGE (1<<1)
#define DRM_MODE_PROP_IMMUTABLE (1<<2)
#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */
#define DRM_MODE_PROP_BLOB (1<<4)
struct drm_mode_property_enum {
uint64_t value;
char name[DRM_PROP_NAME_LEN];
};
struct drm_mode_get_property {
uint64_t values_ptr; /* values and blob lengths */
uint64_t enum_blob_ptr; /* enum and blob id ptrs */
uint32_t prop_id;
uint32_t flags;
char name[DRM_PROP_NAME_LEN];
uint32_t count_values;
uint32_t count_enum_blobs;
};
struct drm_mode_connector_set_property {
uint64_t value;
uint32_t prop_id;
uint32_t connector_id;
};
struct drm_mode_get_blob {
uint32_t blob_id;
uint32_t length;
uint64_t data;
};
struct drm_mode_fb_cmd {
uint32_t fb_id;
uint32_t width, height;
uint32_t pitch;
uint32_t bpp;
uint32_t depth;
/* driver specific handle */
uint32_t handle;
};
struct drm_mode_mode_cmd {
uint32_t connector_id;
struct drm_mode_modeinfo mode;
};
#define DRM_MODE_CURSOR_BO (1<<0)
#define DRM_MODE_CURSOR_MOVE (1<<1)
/*
* depending on the value in flags diffrent members are used.
*
* CURSOR_BO uses
* crtc
* width
* height
* handle - if 0 turns the cursor of
*
* CURSOR_MOVE uses
* crtc
* x
* y
*/
struct drm_mode_cursor {
uint32_t flags;
uint32_t crtc_id;
int32_t x;
int32_t y;
uint32_t width;
uint32_t height;
/* driver specific handle */
uint32_t handle;
};
struct drm_mode_crtc_lut {
uint32_t crtc_id;
uint32_t gamma_size;
/* pointers to arrays */
uint64_t red;
uint64_t green;
uint64_t blue;
};
#endif

View File

@ -15,6 +15,10 @@ libdrmtest_la_LIBADD = \
LDADD = libdrmtest.la LDADD = libdrmtest.la
noinst_SUBDIRS = \
modeprint \
modetest
TESTS = auth \ TESTS = auth \
openclose \ openclose \
getversion \ getversion \

View File

@ -263,7 +263,7 @@ int main(int argc, char **argv)
for (i = 0; i < 16; i++) if (!minor || i == minor) { for (i = 0; i < 16; i++) if (!minor || i == minor) {
sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i); sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i);
fd = drmOpenMinor(i, 1); fd = drmOpenMinor(i, 1, DRM_NODE_RENDER);
if (fd >= 0) { if (fd >= 0) {
printf("%s\n", buf); printf("%s\n", buf);
if (mask & DRM_BUSID) getbusid(fd); if (mask & DRM_BUSID) getbusid(fd);

14
tests/modeprint/Makefile Normal file
View File

@ -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

BIN
tests/modeprint/app Executable file

Binary file not shown.

402
tests/modeprint/modeprint.c Normal file
View File

@ -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;
}

1
tests/modeprint/test Normal file
View File

@ -0,0 +1 @@
LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@

14
tests/modetest/Makefile Normal file
View File

@ -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

449
tests/modetest/modetest.c Normal file
View File

@ -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;
}

2
tests/modetest/test Normal file
View File

@ -0,0 +1,2 @@
export LD_LIBRARY_PATH=../../libdrm/.libs:../../libdrm/intel/.libs
LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@