[PATCH] modetest: add drm_plane support
Rob Clark
rob at ti.com
Wed Dec 14 19:04:30 PST 2011
On Tue, Dec 13, 2011 at 8:55 PM, Rob Clark <rob.clark at linaro.org> wrote:
> From: Rob Clark <rob at ti.com>
>
> Signed-off-by: Rob Clark <rob at ti.com>
> ---
> tests/modetest/modetest.c | 166 ++++++++++++++++++++++++++++++++++++++++++---
> 1 files changed, 157 insertions(+), 9 deletions(-)
>
> diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
> index 1e4ec91..22ac620 100644
> --- a/tests/modetest/modetest.c
> +++ b/tests/modetest/modetest.c
> @@ -51,6 +51,7 @@
>
> #include "xf86drm.h"
> #include "xf86drmMode.h"
> +#include "drm_fourcc.h"
> #include "libkms.h"
>
> #ifdef HAVE_CAIRO
> @@ -267,6 +268,49 @@ void dump_framebuffers(void)
> printf("\n");
> }
>
> +static void dump_planes(void)
> +{
> + drmModePlaneRes *plane_resources;
> + drmModePlane *ovr;
> + 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");
> +
> + drmModeFreePlane(ovr);
> + }
> + printf("\n");
> +
> + return;
> +}
> +
> /*
> * 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
> @@ -280,11 +324,18 @@ struct connector {
> drmModeModeInfo *mode;
> drmModeEncoder *encoder;
> int crtc;
> + int pipe;
> unsigned int fb_id[2], current_fb_id;
> struct timeval start;
>
> int swap_count;
> -};
> +};
> +
> +struct plane {
> + uint32_t con_id; /* the id of connector to bind to */
> + uint32_t w, h;
> + unsigned int fb_id;
> +};
>
> static void
> connector_find_mode(struct connector *c)
> @@ -351,6 +402,15 @@ connector_find_mode(struct connector *c)
>
> 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;
> + }
> + }
> +
> }
>
> static struct kms_bo *
> @@ -534,13 +594,83 @@ page_flip_handler(int fd, unsigned int frame,
> }
> }
>
> +static int
> +set_plane(struct kms_driver *kms, struct connector *c, struct plane *p)
> +{
> + drmModePlaneRes *plane_resources;
> + drmModePlane *ovr;
> + uint32_t handles[4], pitches[4], offsets[4]; /* we only use [0] */
opps, passing unitialized offset values to drmModeAddFB2() causes
problems when the driver doesn't actually ignore the offset..
don't merge this yet.. I'm fixing and also adding some test code for
multi-planar YUV (which will need Joonyoung Shim's fix)
BR,
-R
> + uint32_t plane_id = 0;
> + struct kms_bo *plane_bo;
> + uint32_t plane_flags = 0;
> + int i, crtc_x, crtc_y, crtc_w, crtc_h;
> +
> + /* 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);
> + }
> +
> + if (!plane_id) {
> + fprintf(stderr, "failed to find plane!\n");
> + return -1;
> + }
> +
> + /* TODO.. would be nice to test YUV overlays.. */
> + 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]);
> +
> + /* just use single plane format for now.. */
> + if (drmModeAddFB2(fd, p->w, p->h, DRM_FORMAT_XRGB8888,
> + 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;
> +}
> +
> static void
> -set_mode(struct connector *c, int count, int page_flip)
> +set_mode(struct connector *c, int count, struct plane *p, int plane_count,
> + int page_flip)
> {
> struct kms_driver *kms;
> struct kms_bo *bo, *other_bo;
> unsigned int fb_id, other_fb_id;
> - int i, ret, width, height, x, stride;
> + int i, j, ret, width, height, x, stride;
> unsigned handle;
> drmEventContext evctx;
>
> @@ -593,6 +723,12 @@ set_mode(struct connector *c, int count, int page_flip)
> 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)
> @@ -676,19 +812,20 @@ set_mode(struct connector *c, int count, int page_flip)
>
> extern char *optarg;
> extern int optind, opterr, optopt;
> -static char optstr[] = "ecpmfs:v";
> +static char optstr[] = "ecpmfs:P:v";
>
> 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-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, "\n\tDefault is to dump all info.\n");
> exit(0);
> }
> @@ -719,12 +856,13 @@ static int page_flipping_supported(int fd)
> int main(int argc, char **argv)
> {
> int c;
> - int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0;
> + int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0;
> int test_vsync = 0;
> char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm" };
> char *modeset = NULL;
> - int i, count = 0;
> + int i, count = 0, plane_count = 0;
> struct connector con_args[2];
> + struct plane plane_args[2];
>
> opterr = 0;
> while ((c = getopt(argc, argv, optstr)) != -1) {
> @@ -737,6 +875,7 @@ int main(int argc, char **argv)
> break;
> case 'p':
> crtcs = 1;
> + planes = 1;
> break;
> case 'm':
> modes = 1;
> @@ -760,6 +899,14 @@ int main(int argc, char **argv)
> usage(argv[0]);
> count++;
> break;
> + case 'P':
> + if (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;
> @@ -767,7 +914,7 @@ int main(int argc, char **argv)
> }
>
> if (argc == 1)
> - encoders = connectors = crtcs = modes = framebuffers = 1;
> + encoders = connectors = crtcs = planes = modes = framebuffers = 1;
>
> for (i = 0; i < ARRAY_SIZE(modules); i++) {
> printf("trying to load module %s...", modules[i]);
> @@ -801,10 +948,11 @@ int main(int argc, char **argv)
> dump_resource(encoders);
> dump_resource(connectors);
> dump_resource(crtcs);
> + dump_resource(planes);
> dump_resource(framebuffers);
>
> if (count > 0) {
> - set_mode(con_args, count, test_vsync);
> + set_mode(con_args, count, plane_args, plane_count, test_vsync);
> getchar();
> }
>
> --
> 1.7.5.4
>
More information about the dri-devel
mailing list