Back to index

libdrm  2.4.37
Classes | Defines | Functions | Variables
modetest.c File Reference
#include "config.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/poll.h>
#include <sys/time.h>
#include "xf86drm.h"
#include "xf86drmMode.h"
#include "drm_fourcc.h"
#include "libkms.h"

Go to the source code of this file.

Classes

struct  type_name
struct  connector
struct  plane

Defines

#define ARRAY_SIZE(arr)   (sizeof(arr) / sizeof((arr)[0]))
#define type_name_fn(res)
#define bit_name_fn(res)
#define RED   2
#define GREEN   1
#define BLUE   0
#define dump_resource(res)   if (res) dump_##res()

Functions

 type_name_fn (encoder_type)
 type_name_fn (connector_status)
 type_name_fn (connector_type)
 bit_name_fn (mode_type)
 bit_name_fn (mode_flag)
void dump_mode (drmModeModeInfo *mode)
static void dump_blob (uint32_t blob_id)
static void dump_prop (uint32_t prop_id, uint64_t value)
void dump_connectors (void)
void dump_crtcs (void)
void dump_framebuffers (void)
static void dump_planes (void)
static void connector_find_mode (struct connector *c)
static struct kms_boallocate_buffer (struct kms_driver *kms, int width, int height, int *stride)
static void make_pwetty (void *data, int width, int height, int stride)
static int create_test_buffer (struct kms_driver *kms, int width, int height, int *stride_out, struct kms_bo **bo_out)
static int create_grey_buffer (struct kms_driver *kms, int width, int height, int *stride_out, struct kms_bo **bo_out)
void page_flip_handler (int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
static void fill420 (unsigned char *y, unsigned char *u, unsigned char *v, int cs, int n, int width, int height, int stride)
static void fill422 (unsigned char *virtual, int n, int width, int height, int stride)
static void fill1555 (unsigned char *virtual, int n, int width, int height, int stride)
static int set_plane (struct kms_driver *kms, struct connector *c, struct plane *p)
static void set_mode (struct connector *c, int count, struct plane *p, int plane_count, int page_flip)
void usage (char *name)
static int page_flipping_supported (void)
int main (int argc, char **argv)

Variables

drmModeResresources
int fd
int modes
char * optarg
int optind
int opterr
int optopt
static char optstr [] = "ecpmfs:P:v"

Class Documentation

struct type_name

Definition at line 68 of file modetest.c.

Class Members
char * name
int type
struct connector

Definition at line 484 of file modetest.c.

Collaboration diagram for connector:
Class Members
int crtc
unsigned int current_fb_id
drmModeEncoder * encoder
unsigned int fb_id
uint32_t id
drmModeModeInfo * mode
char mode_str
int pipe
int swap_count
struct plane

Definition at line 497 of file modetest.c.

Class Members
uint32_t con_id
unsigned int fb_id
char format_str
uint32_t h
uint32_t w

Define Documentation

#define ARRAY_SIZE (   arr)    (sizeof(arr) / sizeof((arr)[0]))

Definition at line 66 of file modetest.c.

#define bit_name_fn (   res)
Value:
char * res##_str(int type) {                                   \
       int i;                                           \
       const char *sep = "";                                   \
       for (i = 0; i < ARRAY_SIZE(res##_names); i++) {         \
              if (type & (1 << i)) {                           \
                     printf("%s%s", sep, res##_names[i]);      \
                     sep = ", ";                        \
              }                                         \
       }                                                \
}
#define BLUE   0

Definition at line 764 of file modetest.c.

#define dump_resource (   res)    if (res) dump_##res()

Definition at line 1160 of file modetest.c.

#define GREEN   1

Definition at line 763 of file modetest.c.

#define RED   2

Definition at line 762 of file modetest.c.

#define type_name_fn (   res)
Value:
char * res##_str(int type) {                     \
       unsigned int i;                                  \
       for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
              if (res##_names[i].type == type)   \
                     return res##_names[i].name; \
       }                                         \
       return "(invalid)";                       \
}

Definition at line 73 of file modetest.c.


Function Documentation

static struct kms_bo* allocate_buffer ( struct kms_driver kms,
int  width,
int  height,
int *  stride 
) [static, read]

Definition at line 581 of file modetest.c.

{
       struct kms_bo *bo;
       unsigned bo_attribs[] = {
              KMS_WIDTH,   0,
              KMS_HEIGHT,  0,
              KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
              KMS_TERMINATE_PROP_LIST
       };
       int ret;

       bo_attribs[1] = width;
       bo_attribs[3] = height;

       ret = kms_bo_create(kms, bo_attribs, &bo);
       if (ret) {
              fprintf(stderr, "failed to alloc buffer: %s\n",
                     strerror(-ret));
              return NULL;
       }

       ret = kms_bo_get_prop(bo, KMS_PITCH, stride);
       if (ret) {
              fprintf(stderr, "failed to retreive buffer stride: %s\n",
                     strerror(-ret));
              kms_bo_destroy(&bo);
              return NULL;
       }

       return bo;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bit_name_fn ( mode_type  )

Definition at line 143 of file modetest.c.

                                       {
       "phsync",
       "nhsync",
       "pvsync",
       "nvsync",
       "interlace",
       "dblscan",
       "csync",
       "pcsync",
       "ncsync",
       "hskew",
       "bcast",
       "pixmux",
       "dblclk",
       "clkdiv2"
};
bit_name_fn ( mode_flag  )

Definition at line 162 of file modetest.c.

{
       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);
       }
       printf("\n");
}

Here is the call graph for this function:

static void connector_find_mode ( struct connector c) [static]

Definition at line 505 of file modetest.c.

{
       drmModeConnector *connector;
       int i, j;

       /* First, find the connector & mode */
       c->mode = NULL;
       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 != c->id) {
                     drmModeFreeConnector(connector);
                     continue;
              }

              for (j = 0; j < connector->count_modes; j++) {
                     c->mode = &connector->modes[j];
                     if (!strcmp(c->mode->name, c->mode_str))
                            break;
              }

              /* Found it, break out */
              if (c->mode)
                     break;

              drmModeFreeConnector(connector);
       }

       if (!c->mode) {
              fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
              return;
       }

       /* Now get the encoder */
       for (i = 0; i < resources->count_encoders; i++) {
              c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);

              if (!c->encoder) {
                     fprintf(stderr, "could not get encoder %i: %s\n",
                            resources->encoders[i], strerror(errno));
                     drmModeFreeEncoder(c->encoder);
                     continue;
              }

              if (c->encoder->encoder_id  == connector->encoder_id)
                     break;

              drmModeFreeEncoder(c->encoder);
       }

       if (c->crtc == -1)
              c->crtc = c->encoder->crtc_id;

       /* and figure out which crtc index it is: */
       for (i = 0; i < resources->count_crtcs; i++) {
              if (c->crtc == resources->crtcs[i]) {
                     c->pipe = i;
                     break;
              }
       }

}

Here is the call graph for this function:

Here is the caller graph for this function:

static int create_grey_buffer ( struct kms_driver kms,
int  width,
int  height,
int *  stride_out,
struct kms_bo **  bo_out 
) [static]

Definition at line 702 of file modetest.c.

{
       struct kms_bo *bo;
       int size, ret, stride;
       void *virtual;

       bo = allocate_buffer(kms, width, height, &stride);
       if (!bo)
              return -1;

       ret = kms_bo_map(bo, &virtual);
       if (ret) {
              fprintf(stderr, "failed to map buffer: %s\n",
                     strerror(-ret));
              kms_bo_destroy(&bo);
              return -1;
       }

       size = stride * height;
       memset(virtual, 0x77, size);
       kms_bo_unmap(bo);

       *bo_out = bo;
       *stride_out = stride;

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int create_test_buffer ( struct kms_driver kms,
int  width,
int  height,
int *  stride_out,
struct kms_bo **  bo_out 
) [static]

Definition at line 661 of file modetest.c.

{
       struct kms_bo *bo;
       int ret, i, j, stride;
       void *virtual;

       bo = allocate_buffer(kms, width, height, &stride);
       if (!bo)
              return -1;

       ret = kms_bo_map(bo, &virtual);
       if (ret) {
              fprintf(stderr, "failed to map buffer: %s\n",
                     strerror(-ret));
              kms_bo_destroy(&bo);
              return -1;
       }

       /* paint the buffer with colored tiles */
       for (j = 0; j < height; j++) {
              uint32_t *fb_ptr = (uint32_t*)((char*)virtual + j * stride);
              for (i = 0; i < width; i++) {
                     div_t d = div(i, width);
                     fb_ptr[i] =
                            0x00130502 * (d.quot >> 6) +
                            0x000a1120 * (d.rem >> 6);
              }
       }

       make_pwetty(virtual, width, height, stride);

       kms_bo_unmap(bo);

       *bo_out = bo;
       *stride_out = stride;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dump_blob ( uint32_t  blob_id) [static]

Definition at line 212 of file modetest.c.

{
       uint32_t i;
       unsigned char *blob_data;
       drmModePropertyBlobPtr blob;

       blob = drmModeGetPropertyBlob(fd, blob_id);
       if (!blob)
              return;

       blob_data = blob->data;

       for (i = 0; i < blob->length; i++) {
              if (i % 16 == 0)
                     printf("\n\t\t\t");
              printf("%.2hhx", blob_data[i]);
       }
       printf("\n");

       drmModeFreePropertyBlob(blob);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dump_connectors ( void  )

Definition at line 306 of file modetest.c.

{
       drmModeConnector *connector;
       int i, j;

       printf("Connectors:\n");
       printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\tencoders\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\t",
                     connector->connector_id,
                     connector->encoder_id,
                     connector_status_str(connector->connection),
                     connector_type_str(connector->connector_type),
                     connector->mmWidth, connector->mmHeight,
                     connector->count_modes);

              for (j = 0; j < connector->count_encoders; j++)
                     printf("%s%d", j > 0 ? ", " : "", connector->encoders[j]);
              printf("\n");

              if (connector->count_modes) {
                     printf("  modes:\n");
                     printf("\tname refresh (Hz) hdisp hss hse htot vdisp "
                            "vss vse vtot)\n");
                     for (j = 0; j < connector->count_modes; j++)
                            dump_mode(&connector->modes[j]);

                     printf("  props:\n");
                     for (j = 0; j < connector->count_props; j++)
                            dump_prop(connector->props[j],
                                     connector->prop_values[j]);
              }

              drmModeFreeConnector(connector);
       }
       printf("\n");
}

Here is the call graph for this function:

void dump_crtcs ( void  )

Definition at line 352 of file modetest.c.

{
       drmModeCrtc *crtc;
       drmModeObjectPropertiesPtr props;
       int i;
       uint32_t j;

       printf("CRTCs:\n");
       printf("id\tfb\tpos\tsize\n");
       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;
              }
              printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
                     crtc->crtc_id,
                     crtc->buffer_id,
                     crtc->x, crtc->y,
                     crtc->width, crtc->height);
              dump_mode(&crtc->mode);

              printf("  props:\n");
              props = drmModeObjectGetProperties(fd, crtc->crtc_id,
                                             DRM_MODE_OBJECT_CRTC);
              if (props) {
                     for (j = 0; j < props->count_props; j++)
                            dump_prop(props->props[j],
                                     props->prop_values[j]);
                     drmModeFreeObjectProperties(props);
              } else {
                     printf("\tcould not get crtc properties: %s\n",
                            strerror(errno));
              }

              drmModeFreeCrtc(crtc);
       }
       printf("\n");
}

Here is the call graph for this function:

void dump_framebuffers ( void  )

Definition at line 394 of file modetest.c.

{
       drmModeFB *fb;
       int i;

       printf("Frame buffers:\n");
       printf("id\tsize\tpitch\n");
       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;
              }
              printf("%u\t(%ux%u)\t%u\n",
                     fb->fb_id,
                     fb->width, fb->height,
                     fb->pitch);

              drmModeFreeFB(fb);
       }
       printf("\n");
}

Here is the call graph for this function:

void dump_mode ( drmModeModeInfo mode)

Definition at line 190 of file modetest.c.

{
       printf("  %s %d %d %d %d %d %d %d %d %d",
              mode->name,
              mode->vrefresh,
              mode->hdisplay,
              mode->hsync_start,
              mode->hsync_end,
              mode->htotal,
              mode->vdisplay,
              mode->vsync_start,
              mode->vsync_end,
              mode->vtotal);

       printf(" flags: ");
       mode_flag_str(mode->flags);
       printf("; type: ");
       mode_type_str(mode->type);
       printf("\n");
}

Here is the caller graph for this function:

static void dump_planes ( void  ) [static]

Definition at line 419 of file modetest.c.

{
       drmModeObjectPropertiesPtr props;
       drmModePlaneRes *plane_resources;
       drmModePlane *ovr;
       unsigned int i, j;

       plane_resources = drmModeGetPlaneResources(fd);
       if (!plane_resources) {
              fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
                     strerror(errno));
              return;
       }

       printf("Planes:\n");
       printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\n");
       for (i = 0; i < plane_resources->count_planes; i++) {
              ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
              if (!ovr) {
                     fprintf(stderr, "drmModeGetPlane failed: %s\n",
                            strerror(errno));
                     continue;
              }

              printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%d\n",
                     ovr->plane_id, ovr->crtc_id, ovr->fb_id,
                     ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y,
                     ovr->gamma_size);

              if (!ovr->count_formats)
                     continue;

              printf("  formats:");
              for (j = 0; j < ovr->count_formats; j++)
                     printf(" %4.4s", (char *)&ovr->formats[j]);
              printf("\n");

              printf("  props:\n");
              props = drmModeObjectGetProperties(fd, ovr->plane_id,
                                             DRM_MODE_OBJECT_PLANE);
              if (props) {
                     for (j = 0; j < props->count_props; j++)
                            dump_prop(props->props[j],
                                     props->prop_values[j]);
                     drmModeFreeObjectProperties(props);
              } else {
                     printf("\tcould not get plane properties: %s\n",
                            strerror(errno));
              }

              drmModeFreePlane(ovr);
       }
       printf("\n");

       drmModeFreePlaneResources(plane_resources);
       return;
}

Here is the call graph for this function:

static void dump_prop ( uint32_t  prop_id,
uint64_t  value 
) [static]

Definition at line 235 of file modetest.c.

{
       int i;
       drmModePropertyPtr prop;

       prop = drmModeGetProperty(fd, prop_id);

       printf("\t%d", prop_id);
       if (!prop) {
              printf("\n");
              return;
       }

       printf(" %s:\n", prop->name);

       printf("\t\tflags:");
       if (prop->flags & DRM_MODE_PROP_PENDING)
              printf(" pending");
       if (prop->flags & DRM_MODE_PROP_RANGE)
              printf(" range");
       if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
              printf(" immutable");
       if (prop->flags & DRM_MODE_PROP_ENUM)
              printf(" enum");
       if (prop->flags & DRM_MODE_PROP_BITMASK)
              printf(" bitmask");
       if (prop->flags & DRM_MODE_PROP_BLOB)
              printf(" blob");
       printf("\n");

       if (prop->flags & DRM_MODE_PROP_RANGE) {
              printf("\t\tvalues:");
              for (i = 0; i < prop->count_values; i++)
                     printf(" %"PRIu64, prop->values[i]);
              printf("\n");
       }

       if (prop->flags & DRM_MODE_PROP_ENUM) {
              printf("\t\tenums:");
              for (i = 0; i < prop->count_enums; i++)
                     printf(" %s=%llu", prop->enums[i].name,
                            prop->enums[i].value);
              printf("\n");
       } else if (prop->flags & DRM_MODE_PROP_BITMASK) {
              printf("\t\tvalues:");
              for (i = 0; i < prop->count_enums; i++)
                     printf(" %s=0x%llx", prop->enums[i].name,
                            (1LL << prop->enums[i].value));
              printf("\n");
       } else {
              assert(prop->count_enums == 0);
       }

       if (prop->flags & DRM_MODE_PROP_BLOB) {
              printf("\t\tblobs:\n");
              for (i = 0; i < prop->count_blobs; i++)
                     dump_blob(prop->blob_ids[i]);
              printf("\n");
       } else {
              assert(prop->count_blobs == 0);
       }

       printf("\t\tvalue:");
       if (prop->flags & DRM_MODE_PROP_BLOB)
              dump_blob(value);
       else
              printf(" %"PRIu64"\n", value);

       drmModeFreeProperty(prop);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fill1555 ( unsigned char *  virtual,
int  n,
int  width,
int  height,
int  stride 
) [static]

Definition at line 819 of file modetest.c.

{
       int i, j;
       /* paint the buffer with colored tiles */
       for (j = 0; j < height; j++) {
              uint16_t *ptr = (uint16_t*)((char*)virtual + j * stride);
              for (i = 0; i < width; i++) {
                     div_t d = div(n+i+j, width);
                     uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
                     unsigned char *rgbp = (unsigned char *)&rgb;

                     *(ptr++) = 0x8000 |
                                   (rgbp[RED] >> 3) << 10 |
                                   (rgbp[GREEN] >> 3) << 5 |
                                   (rgbp[BLUE] >> 3);
              }
       }
}

Here is the caller graph for this function:

static void fill420 ( unsigned char *  y,
unsigned char *  u,
unsigned char *  v,
int  cs,
int  n,
int  width,
int  height,
int  stride 
) [static]

Definition at line 767 of file modetest.c.

{
       int i, j;

       /* paint the buffer with colored tiles, in blocks of 2x2 */
       for (j = 0; j < height; j+=2) {
              unsigned char *y1p = y + j * stride;
              unsigned char *y2p = y1p + stride;
              unsigned char *up = u + (j/2) * stride * cs / 2;
              unsigned char *vp = v + (j/2) * stride * cs / 2;

              for (i = 0; i < width; i+=2) {
                     div_t d = div(n+i+j, width);
                     uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
                     unsigned char *rgbp = (unsigned char *)&rgb;
                     unsigned char y = (0.299 * rgbp[RED]) + (0.587 * rgbp[GREEN]) + (0.114 * rgbp[BLUE]);

                     *(y2p++) = *(y1p++) = y;
                     *(y2p++) = *(y1p++) = y;

                     *up = (rgbp[BLUE] - y) * 0.565 + 128;
                     *vp = (rgbp[RED] - y) * 0.713 + 128;
                     up += cs;
                     vp += cs;
              }
       }
}

Here is the caller graph for this function:

static void fill422 ( unsigned char *  virtual,
int  n,
int  width,
int  height,
int  stride 
) [static]

Definition at line 798 of file modetest.c.

{
       int i, j;
       /* paint the buffer with colored tiles */
       for (j = 0; j < height; j++) {
              uint8_t *ptr = (uint8_t*)((char*)virtual + j * stride);
              for (i = 0; i < width; i++) {
                     div_t d = div(n+i+j, width);
                     uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
                     unsigned char *rgbp = (unsigned char *)&rgb;
                     unsigned char y = (0.299 * rgbp[RED]) + (0.587 * rgbp[GREEN]) + (0.114 * rgbp[BLUE]);

                     *(ptr++) = y;
                     *(ptr++) = (rgbp[BLUE] - y) * 0.565 + 128;
                     *(ptr++) = y;
                     *(ptr++) = (rgbp[RED] - y) * 0.713 + 128;
              }
       }
}

Here is the caller graph for this function:

int main ( int  argc,
char **  argv 
)

Definition at line 1183 of file modetest.c.

{
       int c;
       int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0;
       int test_vsync = 0;
       char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos" };
       unsigned int i;
       int count = 0, plane_count = 0;
       struct connector con_args[2];
       struct plane plane_args[2] = {0};
       
       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;
                     planes = 1;
                     break;
              case 'm':
                     modes = 1;
                     break;
              case 'f':
                     framebuffers = 1;
                     break;
              case 'v':
                     test_vsync = 1;
                     break;
              case 's':
                     con_args[count].crtc = -1;
                     if (sscanf(optarg, "%d:%64s",
                               &con_args[count].id,
                               con_args[count].mode_str) != 2 &&
                         sscanf(optarg, "%d@%d:%64s",
                               &con_args[count].id,
                               &con_args[count].crtc,
                               con_args[count].mode_str) != 3)
                            usage(argv[0]);
                     count++;                                 
                     break;
              case 'P':
                     strcpy(plane_args[plane_count].format_str, "XR24");
                     if (sscanf(optarg, "%d:%dx%d@%4s",
                                   &plane_args[plane_count].con_id,
                                   &plane_args[plane_count].w,
                                   &plane_args[plane_count].h,
                                   plane_args[plane_count].format_str) != 4 &&
                            sscanf(optarg, "%d:%dx%d",
                                   &plane_args[plane_count].con_id,
                                   &plane_args[plane_count].w,
                                   &plane_args[plane_count].h) != 3)
                            usage(argv[0]);
                     plane_count++;
                     break;
              default:
                     usage(argv[0]);
                     break;
              }
       }

       if (argc == 1)
              encoders = connectors = crtcs = planes = 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 (test_vsync && !page_flipping_supported()) {
              fprintf(stderr, "page flipping not supported by drm.\n");
              return -1;
       }

       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(planes);
       dump_resource(framebuffers);

       if (count > 0) {
              set_mode(con_args, count, plane_args, plane_count, test_vsync);
              getchar();
       }

       drmModeFreeResources(resources);

       return 0;
}

Here is the call graph for this function:

static void make_pwetty ( void *  data,
int  width,
int  height,
int  stride 
) [static]

Definition at line 615 of file modetest.c.

{
#ifdef HAVE_CAIRO
       cairo_surface_t *surface;
       cairo_t *cr;
       int x, y;

       surface = cairo_image_surface_create_for_data(data,
                                                CAIRO_FORMAT_ARGB32,
                                                width, height,
                                                stride);
       cr = cairo_create(surface);
       cairo_surface_destroy(surface);

       cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
       for (x = 0; x < width; x += 250)
              for (y = 0; y < height; y += 250) {
                     char buf[64];

                     cairo_move_to(cr, x, y - 20);
                     cairo_line_to(cr, x, y + 20);
                     cairo_move_to(cr, x - 20, y);
                     cairo_line_to(cr, x + 20, y);
                     cairo_new_sub_path(cr);
                     cairo_arc(cr, x, y, 10, 0, M_PI * 2);
                     cairo_set_line_width(cr, 4);
                     cairo_set_source_rgb(cr, 0, 0, 0);
                     cairo_stroke_preserve(cr);
                     cairo_set_source_rgb(cr, 1, 1, 1);
                     cairo_set_line_width(cr, 2);
                     cairo_stroke(cr);

                     snprintf(buf, sizeof buf, "%d, %d", x, y);
                     cairo_move_to(cr, x + 20, y + 20);
                     cairo_text_path(cr, buf);
                     cairo_set_source_rgb(cr, 0, 0, 0);
                     cairo_stroke_preserve(cr);
                     cairo_set_source_rgb(cr, 1, 1, 1);
                     cairo_fill(cr);
              }

       cairo_destroy(cr);
#endif
}

Here is the caller graph for this function:

void page_flip_handler ( int  fd,
unsigned int  frame,
unsigned int  sec,
unsigned int  usec,
void *  data 
)

Definition at line 733 of file modetest.c.

{
       struct connector *c;
       unsigned int new_fb_id;
       struct timeval end;
       double t;

       c = data;
       if (c->current_fb_id == c->fb_id[0])
              new_fb_id = c->fb_id[1];
       else
              new_fb_id = c->fb_id[0];
                     
       drmModePageFlip(fd, c->crtc, new_fb_id,
                     DRM_MODE_PAGE_FLIP_EVENT, c);
       c->current_fb_id = new_fb_id;
       c->swap_count++;
       if (c->swap_count == 60) {
              gettimeofday(&end, NULL);
              t = end.tv_sec + end.tv_usec * 1e-6 -
                     (c->start.tv_sec + c->start.tv_usec * 1e-6);
              fprintf(stderr, "freq: %.02fHz\n", c->swap_count / t);
              c->swap_count = 0;
              c->start = end;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int page_flipping_supported ( void  ) [static]

Definition at line 1162 of file modetest.c.

{
       /*FIXME: generic ioctl needed? */
       return 1;
#if 0
       int ret, value;
       struct drm_i915_getparam gp;

       gp.param = I915_PARAM_HAS_PAGEFLIPPING;
       gp.value = &value;

       ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
       if (ret) {
              fprintf(stderr, "drm_i915_getparam: %m\n");
              return 0;
       }

       return *gp.value;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void set_mode ( struct connector c,
int  count,
struct plane p,
int  plane_count,
int  page_flip 
) [static]

Definition at line 993 of file modetest.c.

{
       struct kms_driver *kms;
       struct kms_bo *bo, *other_bo;
       unsigned int fb_id, other_fb_id;
       int i, j, ret, width, height, x, stride;
       unsigned handle;
       drmEventContext evctx;

       width = 0;
       height = 0;
       for (i = 0; i < count; i++) {
              connector_find_mode(&c[i]);
              if (c[i].mode == NULL)
                     continue;
              width += c[i].mode->hdisplay;
              if (height < c[i].mode->vdisplay)
                     height = c[i].mode->vdisplay;
       }

       ret = kms_create(fd, &kms);
       if (ret) {
              fprintf(stderr, "failed to create kms driver: %s\n",
                     strerror(-ret));
              return;
       }

       if (create_test_buffer(kms, width, height, &stride, &bo))
              return;

       kms_bo_get_prop(bo, KMS_HANDLE, &handle);
       ret = drmModeAddFB(fd, width, height, 24, 32, stride, handle, &fb_id);
       if (ret) {
              fprintf(stderr, "failed to add fb (%ux%u): %s\n",
                     width, height, strerror(errno));
              return;
       }

       x = 0;
       for (i = 0; i < count; i++) {
              if (c[i].mode == NULL)
                     continue;

              printf("setting mode %s on connector %d, crtc %d\n",
                     c[i].mode_str, c[i].id, c[i].crtc);

              ret = drmModeSetCrtc(fd, c[i].crtc, fb_id, x, 0,
                                 &c[i].id, 1, c[i].mode);

              /* XXX: Actually check if this is needed */
              drmModeDirtyFB(fd, fb_id, NULL, 0);

              x += c[i].mode->hdisplay;

              if (ret) {
                     fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
                     return;
              }

              /* if we have a plane/overlay to show, set that up now: */
              for (j = 0; j < plane_count; j++)
                     if (p[j].con_id == c[i].id)
                            if (set_plane(kms, &c[i], &p[j]))
                                   return;
       }

       if (!page_flip)
              return;
       
       if (create_grey_buffer(kms, width, height, &stride, &other_bo))
              return;

       kms_bo_get_prop(other_bo, KMS_HANDLE, &handle);
       ret = drmModeAddFB(fd, width, height, 32, 32, stride, handle,
                        &other_fb_id);
       if (ret) {
              fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
              return;
       }

       for (i = 0; i < count; i++) {
              if (c[i].mode == NULL)
                     continue;

              ret = drmModePageFlip(fd, c[i].crtc, other_fb_id,
                                  DRM_MODE_PAGE_FLIP_EVENT, &c[i]);
              if (ret) {
                     fprintf(stderr, "failed to page flip: %s\n", strerror(errno));
                     return;
              }
              gettimeofday(&c[i].start, NULL);
              c[i].swap_count = 0;
              c[i].fb_id[0] = fb_id;
              c[i].fb_id[1] = other_fb_id;
              c[i].current_fb_id = other_fb_id;
       }

       memset(&evctx, 0, sizeof evctx);
       evctx.version = DRM_EVENT_CONTEXT_VERSION;
       evctx.vblank_handler = NULL;
       evctx.page_flip_handler = page_flip_handler;
       
       while (1) {
#if 0
              struct pollfd pfd[2];

              pfd[0].fd = 0;
              pfd[0].events = POLLIN;
              pfd[1].fd = fd;
              pfd[1].events = POLLIN;

              if (poll(pfd, 2, -1) < 0) {
                     fprintf(stderr, "poll error\n");
                     break;
              }

              if (pfd[0].revents)
                     break;
#else
              struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
              fd_set fds;
              int ret;

              FD_ZERO(&fds);
              FD_SET(0, &fds);
              FD_SET(fd, &fds);
              ret = select(fd + 1, &fds, NULL, NULL, &timeout);

              if (ret <= 0) {
                     fprintf(stderr, "select timed out or error (ret %d)\n",
                            ret);
                     continue;
              } else if (FD_ISSET(0, &fds)) {
                     break;
              }
#endif

              drmHandleEvent(fd, &evctx);
       }

       kms_bo_destroy(&bo);
       kms_bo_destroy(&other_bo);
       kms_destroy(&kms);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int set_plane ( struct kms_driver kms,
struct connector c,
struct plane p 
) [static]

Definition at line 839 of file modetest.c.

{
       drmModePlaneRes *plane_resources;
       drmModePlane *ovr;
       uint32_t handles[4], pitches[4], offsets[4] = {0}; /* we only use [0] */
       uint32_t plane_id = 0;
       struct kms_bo *plane_bo;
       uint32_t plane_flags = 0, format;
       int ret, crtc_x, crtc_y, crtc_w, crtc_h;
       unsigned int i;

       /* find an unused plane which can be connected to our crtc */
       plane_resources = drmModeGetPlaneResources(fd);
       if (!plane_resources) {
              fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
                     strerror(errno));
              return -1;
       }

       for (i = 0; i < plane_resources->count_planes && !plane_id; i++) {
              ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
              if (!ovr) {
                     fprintf(stderr, "drmModeGetPlane failed: %s\n",
                            strerror(errno));
                     return -1;
              }

              if ((ovr->possible_crtcs & (1 << c->pipe)) && !ovr->crtc_id)
                     plane_id = ovr->plane_id;

              drmModeFreePlane(ovr);
       }

       fprintf(stderr, "testing %dx%d@%s overlay plane\n",
                     p->w, p->h, p->format_str);

       if (!plane_id) {
              fprintf(stderr, "failed to find plane!\n");
              return -1;
       }

       if (!strcmp(p->format_str, "XR24")) {
              if (create_test_buffer(kms, p->w, p->h, &pitches[0], &plane_bo))
                     return -1;
              kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
              format = DRM_FORMAT_XRGB8888;
       } else {
              void *virtual;

              /* TODO: this always allocates a buffer for 32bpp RGB.. but for
               * YUV formats, we don't use all of it..  since 4bytes/pixel is
               * worst case, so live with it for now and just don't use all
               * the buffer:
               */
              plane_bo = allocate_buffer(kms, p->w, p->h, &pitches[0]);
              if (!plane_bo)
                     return -1;

              ret = kms_bo_map(plane_bo, &virtual);
              if (ret) {
                     fprintf(stderr, "failed to map buffer: %s\n",
                            strerror(-ret));
                     kms_bo_destroy(&plane_bo);
                     return -1;
              }

              /* just testing a limited # of formats to test single
               * and multi-planar path.. would be nice to add more..
               */
              if (!strcmp(p->format_str, "YUYV")) {
                     pitches[0] = p->w * 2;
                     offsets[0] = 0;
                     kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);

                     fill422(virtual, 0, p->w, p->h, pitches[0]);

                     format = DRM_FORMAT_YUYV;
              } else if (!strcmp(p->format_str, "NV12")) {
                     pitches[0] = p->w;
                     offsets[0] = 0;
                     kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
                     pitches[1] = p->w;
                     offsets[1] = p->w * p->h;
                     kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[1]);

                     fill420(virtual, virtual+offsets[1], virtual+offsets[1]+1,
                                   2, 0, p->w, p->h, pitches[0]);

                     format = DRM_FORMAT_NV12;
              } else if (!strcmp(p->format_str, "YV12")) {
                     pitches[0] = p->w;
                     offsets[0] = 0;
                     kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
                     pitches[1] = p->w / 2;
                     offsets[1] = p->w * p->h;
                     kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[1]);
                     pitches[2] = p->w / 2;
                     offsets[2] = offsets[1] + (p->w * p->h) / 4;
                     kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[2]);

                     fill420(virtual, virtual+offsets[1], virtual+offsets[2],
                                   1, 0, p->w, p->h, pitches[0]);

                     format = DRM_FORMAT_YVU420;
              } else if (!strcmp(p->format_str, "XR15")) {
                     pitches[0] = p->w * 2;
                     offsets[0] = 0;
                     kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);

                     fill1555(virtual, 0, p->w, p->h, pitches[0]);

                     format = DRM_FORMAT_XRGB1555;
              } else if (!strcmp(p->format_str, "AR15")) {
                     pitches[0] = p->w * 2;
                     offsets[0] = 0;
                     kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);

                     fill1555(virtual, 0, p->w, p->h, pitches[0]);

                     format = DRM_FORMAT_ARGB1555;
              } else {
                     fprintf(stderr, "Unknown format: %s\n", p->format_str);
                     return -1;
              }

              kms_bo_unmap(plane_bo);
       }

       /* just use single plane format for now.. */
       if (drmModeAddFB2(fd, p->w, p->h, format,
                     handles, pitches, offsets, &p->fb_id, plane_flags)) {
              fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
              return -1;
       }

       /* ok, boring.. but for now put in middle of screen: */
       crtc_x = c->mode->hdisplay / 3;
       crtc_y = c->mode->vdisplay / 3;
       crtc_w = crtc_x;
       crtc_h = crtc_y;

       /* note src coords (last 4 args) are in Q16 format */
       if (drmModeSetPlane(fd, plane_id, c->crtc, p->fb_id,
                         plane_flags, crtc_x, crtc_y, crtc_w, crtc_h,
                         0, 0, p->w << 16, p->h << 16)) {
              fprintf(stderr, "failed to enable plane: %s\n",
                     strerror(errno));
              return -1;
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

type_name_fn ( encoder_type  )

Definition at line 91 of file modetest.c.

                                            {
       { DRM_MODE_CONNECTED, "connected" },
       { DRM_MODE_DISCONNECTED, "disconnected" },
       { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
};
type_name_fn ( connector_status  )

Definition at line 99 of file modetest.c.

                                          {
       { 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" },
       { DRM_MODE_CONNECTOR_TV, "TV" },
       { DRM_MODE_CONNECTOR_eDP, "embedded displayport" },
};
type_name_fn ( connector_type  )

Definition at line 119 of file modetest.c.

                           {                                   \
       int i;                                           \
       const char *sep = "";                                   \
       for (i = 0; i < ARRAY_SIZE(res##_names); i++) {         \
              if (type & (1 << i)) {                           \
                     printf("%s%s", sep, res##_names[i]);      \
                     sep = ", ";                        \
              }                                         \
       }                                                \
}

static const char *mode_type_names[] = {
       "builtin",
       "clock_c",
       "crtc_c",
       "preferred",
       "default",
       "userdef",
       "driver",
};
void usage ( char *  name)

Definition at line 1143 of file modetest.c.

{
       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 and planes (pipes)\n");
       fprintf(stderr, "\t-m\tlist modes\n");
       fprintf(stderr, "\t-f\tlist framebuffers\n");
       fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
       fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
       fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n");
       fprintf(stderr, "\t-P <connector_id>:<w>x<h>\tset a plane\n");
       fprintf(stderr, "\t-P <connector_id>:<w>x<h>@<format>\tset a plane\n");
       fprintf(stderr, "\n\tDefault is to dump all info.\n");
       exit(0);
}

Here is the caller graph for this function:


Variable Documentation

int fd

Definition at line 64 of file modetest.c.

int modes

Definition at line 64 of file modetest.c.

char* optarg
int opterr
int optind
int optopt
char optstr[] = "ecpmfs:P:v" [static]

Definition at line 1141 of file modetest.c.

Definition at line 63 of file modetest.c.