On Tue, Apr 16, 2019 at 09:43:49AM -0700, John Stultz wrote:
> In trying to further align the AOSP libdrm branch with upstream,
> I wanted to submit the added test planetest that they have been
> carrying for awhile.
> 
> Mostly sending this out for initial reactions and to stir some
> discussion on if folks think upstreaming this would be useful.

I'll start :)

IMO, we should just punt this into orbit. I just wrote it to do some very basic
testing when atomic was first being developed. I think modetest does all of
this and more, not to mention igt which does _much_ more. So unless someone
actually uses this, and has a compelling reason to upstream it I'd say revert it
from Android and we'll be in sync.

> Feedback and thoughts would be appreciated!
> 

/snip

> +int main(int argc, char *argv[])
> +{
> +     int ret, i, j, num_test_planes;
> +     int x_inc = 1, x = 0, y_inc = 1, y = 0;
> +     uint32_t plane_w = 128, plane_h = 128;
> +     struct sp_dev *dev;
> +     struct sp_plane **plane = NULL;
> +     struct sp_crtc *test_crtc;

Terrible names for these structs, geez!

Sean

> +     fd_set fds;
> +     drmModeAtomicReqPtr pset;
> +     drmEventContext event_context = {
> +             .version = DRM_EVENT_CONTEXT_VERSION,
> +             .page_flip_handler = page_flip_handler,
> +     };
> +     int card = 0, crtc = 0;
> +
> +     signal(SIGINT, sigint_handler);
> +
> +     parse_arguments(argc, argv, &card, &crtc);
> +
> +     dev = create_sp_dev(card);
> +     if (!dev) {
> +             printf("Failed to create sp_dev\n");
> +             return -1;
> +     }
> +
> +     if (crtc >= dev->num_crtcs) {
> +             printf("Invalid crtc %d (num=%d)\n", crtc, dev->num_crtcs);
> +             return -1;
> +     }
> +
> +     ret = initialize_screens(dev);
> +     if (ret) {
> +             printf("Failed to initialize screens\n");
> +             goto out;
> +     }
> +     test_crtc = &dev->crtcs[crtc];
> +
> +     plane = calloc(dev->num_planes, sizeof(*plane));
> +     if (!plane) {
> +             printf("Failed to allocate plane array\n");
> +             goto out;
> +     }
> +
> +     /* Create our planes */
> +     num_test_planes = test_crtc->num_planes;
> +     for (i = 0; i < num_test_planes; i++) {
> +             plane[i] = get_sp_plane(dev, test_crtc);
> +             if (!plane[i]) {
> +                     printf("no unused planes available\n");
> +                     goto out;
> +             }
> +
> +             plane[i]->bo = create_sp_bo(dev, plane_w, plane_h, 16, 
> plane[i]->format, 0);
> +             if (!plane[i]->bo) {
> +                     printf("failed to create plane bo\n");
> +                     goto out;
> +             }
> +
> +             fill_bo(plane[i]->bo, 0xFF, 0xFF, 0xFF, 0xFF);
> +     }
> +
> +     pset = drmModeAtomicAlloc();
> +     if (!pset) {
> +             printf("Failed to allocate the property set\n");
> +             goto out;
> +     }
> +
> +     while (!terminate) {
> +             FD_ZERO(&fds);
> +             FD_SET(dev->fd, &fds);
> +
> +             incrementor(&x_inc, &x, 5, 0,
> +                     test_crtc->crtc->mode.hdisplay - plane_w);
> +             incrementor(&y_inc, &y, 5, 0, test_crtc->crtc->mode.vdisplay -
> +                                             plane_h * num_test_planes);
> +
> +             for (j = 0; j < num_test_planes; j++) {
> +                     ret = set_sp_plane_pset(dev, plane[j], pset, test_crtc,
> +                                     x, y + j * plane_h);
> +                     if (ret) {
> +                             printf("failed to move plane %d\n", ret);
> +                             goto out;
> +                     }
> +             }
> +
> +             ret = drmModeAtomicCommit(dev->fd, pset,
> +                                     DRM_MODE_PAGE_FLIP_EVENT, NULL);
> +             if (ret) {
> +                     printf("failed to commit properties ret=%d\n", ret);
> +                     goto out;
> +             }
> +
> +             do {
> +                     ret = select(dev->fd + 1, &fds, NULL, NULL, NULL);
> +             } while (ret == -1 && errno == EINTR);
> +
> +             if (FD_ISSET(dev->fd, &fds))
> +                     drmHandleEvent(dev->fd, &event_context);
> +     }
> +
> +     drmModeAtomicFree(pset);
> +
> +     for (i = 0; i < num_test_planes; i++)
> +             put_sp_plane(plane[i]);
> +
> +out:
> +     destroy_sp_dev(dev);
> +     free(plane);
> +     return ret;
> +}
> diff --git a/tests/planetest/bo.c b/tests/planetest/bo.c
> new file mode 100644
> index 0000000..d4b82c6
> --- /dev/null
> +++ b/tests/planetest/bo.c
> @@ -0,0 +1,234 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/mman.h>
> +#include <fcntl.h>
> +#include <errno.h>
> +
> +#include <xf86drm.h>
> +#include <xf86drmMode.h>
> +#include <drm_fourcc.h>
> +
> +#include "bo.h"
> +#include "dev.h"
> +
> +#define MAKE_YUV_601_Y(r, g, b) \
> +     ((( 66 * (r) + 129 * (g) +  25 * (b) + 128) >> 8) + 16)
> +#define MAKE_YUV_601_U(r, g, b) \
> +     (((-38 * (r) -  74 * (g) + 112 * (b) + 128) >> 8) + 128)
> +#define MAKE_YUV_601_V(r, g, b) \
> +     (((112 * (r) -  94 * (g) -  18 * (b) + 128) >> 8) + 128)
> +
> +static void draw_rect_yuv(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t 
> width,
> +             uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b)
> +{
> +     uint32_t i, j, xmax = x + width, ymax = y + height;
> +
> +     if (xmax > bo->width)
> +             xmax = bo->width;
> +     if (ymax > bo->height)
> +             ymax = bo->height;
> +
> +     for (i = y; i < ymax; i++) {
> +             uint8_t *luma = bo->map_addr + i * bo->pitch;
> +
> +             for (j = x; j < xmax; j++)
> +                     luma[j] = MAKE_YUV_601_Y(r, g, b);
> +     }
> +
> +     for (i = y; i < ymax / 2; i++) {
> +             uint8_t *chroma = bo->map_addr + (i + height) * bo->pitch;
> +
> +             for (j = x; j < xmax / 2; j++) {
> +                     chroma[j*2] = MAKE_YUV_601_U(r, g, b);
> +                     chroma[j*2 + 1] = MAKE_YUV_601_V(r, g, b);
> +             }
> +     }
> +}
> +
> +void fill_bo(struct sp_bo *bo, uint8_t a, uint8_t r, uint8_t g, uint8_t b)
> +{
> +     if (bo->format == DRM_FORMAT_NV12)
> +             draw_rect_yuv(bo, 0, 0, bo->width, bo->height, a, r, g, b);
> +     else
> +             draw_rect(bo, 0, 0, bo->width, bo->height, a, r, g, b);
> +}
> +
> +void draw_rect(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t width,
> +             uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b)
> +{
> +     uint32_t i, j, xmax = x + width, ymax = y + height;
> +
> +     if (xmax > bo->width)
> +             xmax = bo->width;
> +     if (ymax > bo->height)
> +             ymax = bo->height;
> +
> +     for (i = y; i < ymax; i++) {
> +             uint8_t *row = bo->map_addr + i * bo->pitch;
> +
> +             for (j = x; j < xmax; j++) {
> +                     uint8_t *pixel = row + j * 4;
> +
> +                     if (bo->format == DRM_FORMAT_ARGB8888 ||
> +                         bo->format == DRM_FORMAT_XRGB8888)
> +                     {
> +                             pixel[0] = b;
> +                             pixel[1] = g;
> +                             pixel[2] = r;
> +                             pixel[3] = a;
> +                     } else if (bo->format == DRM_FORMAT_RGBA8888) {
> +                             pixel[0] = r;
> +                             pixel[1] = g;
> +                             pixel[2] = b;
> +                             pixel[3] = a;
> +                     }
> +             }
> +     }
> +}
> +
> +static int add_fb_sp_bo(struct sp_bo *bo, uint32_t format)
> +{
> +     int ret;
> +     uint32_t handles[4], pitches[4], offsets[4];
> +
> +     handles[0] = bo->handle;
> +     pitches[0] = bo->pitch;
> +     offsets[0] = 0;
> +     if (bo->format == DRM_FORMAT_NV12) {
> +             handles[1] = bo->handle;
> +             pitches[1] = pitches[0];
> +             offsets[1] = pitches[0] * bo->height;
> +     }
> +
> +     ret = drmModeAddFB2(bo->dev->fd, bo->width, bo->height,
> +                     format, handles, pitches, offsets,
> +                     &bo->fb_id, bo->flags);
> +     if (ret) {
> +             printf("failed to create fb ret=%d\n", ret);
> +             return ret;
> +     }
> +     return 0;
> +}
> +
> +static int map_sp_bo(struct sp_bo *bo)
> +{
> +     int ret;
> +     struct drm_mode_map_dumb md;
> +
> +     if (bo->map_addr)
> +             return 0;
> +
> +     md.handle = bo->handle;
> +     ret = drmIoctl(bo->dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &md);
> +     if (ret) {
> +             printf("failed to map sp_bo ret=%d\n", ret);
> +             return ret;
> +     }
> +
> +     bo->map_addr = mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
> +                             bo->dev->fd, md.offset);
> +     if (bo->map_addr == MAP_FAILED) {
> +             printf("failed to map bo ret=%d\n", -errno);
> +             return -errno;
> +     }
> +     return 0;
> +}
> +
> +static int format_to_bpp(uint32_t format)
> +{
> +     switch (format) {
> +     case DRM_FORMAT_NV12:
> +             return 8;
> +     case DRM_FORMAT_ARGB8888:
> +     case DRM_FORMAT_XRGB8888:
> +     case DRM_FORMAT_RGBA8888:
> +     default:
> +             return 32;
> +     }
> +}
> +
> +struct sp_bo *create_sp_bo(struct sp_dev *dev, uint32_t width, uint32_t 
> height,
> +             uint32_t depth, uint32_t format, uint32_t flags)
> +{
> +     int ret;
> +     struct drm_mode_create_dumb cd;
> +     struct sp_bo *bo;
> +
> +     bo = calloc(1, sizeof(*bo));
> +     if (!bo)
> +             return NULL;
> +
> +     if (format == DRM_FORMAT_NV12)
> +             cd.height = height * 3 / 2;
> +     else
> +             cd.height = height;
> +
> +     cd.width = width;
> +     cd.bpp = format_to_bpp(format);
> +     cd.flags = flags;
> +
> +     ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATE_DUMB, &cd);
> +     if (ret) {
> +             printf("failed to create sp_bo %d\n", ret);
> +             goto err;
> +     }
> +
> +     bo->dev = dev;
> +     bo->width = width;
> +     bo->height = height;
> +     bo->depth = depth;
> +     bo->bpp = format_to_bpp(format);
> +     bo->format = format;
> +     bo->flags = flags;
> +
> +     bo->handle = cd.handle;
> +     bo->pitch = cd.pitch;
> +     bo->size = cd.size;
> +
> +     ret = add_fb_sp_bo(bo, format);
> +     if (ret) {
> +             printf("failed to add fb ret=%d\n", ret);
> +             goto err;
> +     }
> +
> +     ret = map_sp_bo(bo);
> +     if (ret) {
> +             printf("failed to map bo ret=%d\n", ret);
> +             goto err;
> +     }
> +
> +     return bo;
> +
> +err:
> +     free_sp_bo(bo);
> +     return NULL;
> +}
> +
> +void free_sp_bo(struct sp_bo *bo)
> +{
> +     int ret;
> +     struct drm_mode_destroy_dumb dd;
> +
> +     if (!bo)
> +             return;
> +
> +     if (bo->map_addr)
> +             munmap(bo->map_addr, bo->size);
> +
> +     if (bo->fb_id) {
> +             ret = drmModeRmFB(bo->dev->fd, bo->fb_id);
> +             if (ret)
> +                     printf("Failed to rmfb ret=%d!\n", ret);
> +     }
> +
> +     if (bo->handle) {
> +             dd.handle = bo->handle;
> +             ret = drmIoctl(bo->dev->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dd);
> +             if (ret)
> +                     printf("Failed to destroy buffer ret=%d\n", ret);
> +     }
> +
> +     free(bo);
> +}
> diff --git a/tests/planetest/bo.h b/tests/planetest/bo.h
> new file mode 100644
> index 0000000..7471e12
> --- /dev/null
> +++ b/tests/planetest/bo.h
> @@ -0,0 +1,34 @@
> +#ifndef __BO_H_INCLUDED__
> +#define __BO_H_INCLUDED__
> +
> +#include <stdint.h>
> +
> +struct sp_dev;
> +
> +struct sp_bo {
> +     struct sp_dev *dev;
> +
> +     uint32_t width;
> +     uint32_t height;
> +     uint32_t depth;
> +     uint32_t bpp;
> +     uint32_t format;
> +     uint32_t flags;
> +
> +     uint32_t fb_id;
> +     uint32_t handle;
> +     void *map_addr;
> +     uint32_t pitch;
> +     uint32_t size;
> +};
> +
> +struct sp_bo *create_sp_bo(struct sp_dev *dev, uint32_t width, uint32_t 
> height,
> +             uint32_t depth, uint32_t format, uint32_t flags);
> +
> +void fill_bo(struct sp_bo *bo, uint8_t a, uint8_t r, uint8_t g, uint8_t b);
> +void draw_rect(struct sp_bo *bo, uint32_t x, uint32_t y, uint32_t width,
> +             uint32_t height, uint8_t a, uint8_t r, uint8_t g, uint8_t b);
> +
> +void free_sp_bo(struct sp_bo *bo);
> +
> +#endif /* __BO_H_INCLUDED__ */
> diff --git a/tests/planetest/dev.c b/tests/planetest/dev.c
> new file mode 100644
> index 0000000..bd0968c
> --- /dev/null
> +++ b/tests/planetest/dev.c
> @@ -0,0 +1,367 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <getopt.h>
> +
> +#include <drm.h>
> +#include <drm_fourcc.h>
> +#include <errno.h>
> +#include <xf86drm.h>
> +#include <xf86drmMode.h>
> +
> +#include "bo.h"
> +#include "dev.h"
> +#include "modeset.h"
> +
> +static void show_usage(char *name)
> +{
> +     printf("Usage: %s [OPTION]\n", name);
> +     printf("   -c, --card      Index of dri card (ie: /dev/dri/cardN)\n");
> +     printf("   -r, --crtc      Index of crtc to use for test\n");
> +     printf("\n\n");
> +}
> +
> +void parse_arguments(int argc, char *argv[], int *card, int *crtc)
> +{
> +     static struct option options[] = {
> +             { "card", required_argument, NULL, 'c' },
> +             { "crtc", required_argument, NULL, 'r' },
> +             { "help", no_argument, NULL, 'h' },
> +     };
> +     int option_index = 0;
> +     int c;
> +
> +     *card = -1;
> +     *crtc = -1;
> +     do {
> +             c = getopt_long(argc, argv, "c:r:h", options, &option_index);
> +             switch (c) {
> +             case 0:
> +             case 'h':
> +                     show_usage(argv[0]);
> +                     exit(0);
> +             case -1:
> +                     break;
> +             case 'c':
> +                     if (optarg[0] < '0' || optarg[0] > '9') {
> +                             printf("Invalid card value '%s'!\n", optarg);
> +                             show_usage(argv[0]);
> +                             exit(-1);
> +                     }
> +                     *card = optarg[0] - '0';
> +                     break;
> +             case 'r':
> +                     if (optarg[0] < '0' || optarg[0] > '9') {
> +                             printf("Invalid crtc value '%s'!\n", optarg);
> +                             show_usage(argv[0]);
> +                             exit(-1);
> +                     }
> +                     *crtc = optarg[0] - '0';
> +                     break;
> +             }
> +     } while (c != -1);
> +
> +     if (*card < 0 || *crtc < 0) {
> +             show_usage(argv[0]);
> +             exit(-1);
> +     }
> +}
> +
> +static uint32_t get_prop_id(struct sp_dev *dev,
> +                     drmModeObjectPropertiesPtr props, const char *name)
> +{
> +     drmModePropertyPtr p;
> +     uint32_t i, prop_id = 0; /* Property ID should always be > 0 */
> +
> +     for (i = 0; !prop_id && i < props->count_props; i++) {
> +             p = drmModeGetProperty(dev->fd, props->props[i]);
> +             if (!strcmp(p->name, name))
> +                     prop_id = p->prop_id;
> +             drmModeFreeProperty(p);
> +     }
> +     if (!prop_id)
> +             printf("Could not find %s property\n", name);
> +     return prop_id;
> +}
> +
> +static int get_supported_format(struct sp_plane *plane, uint32_t *format)
> +{
> +     uint32_t i;
> +
> +     for (i = 0; i < plane->plane->count_formats; i++) {
> +             if (plane->plane->formats[i] == DRM_FORMAT_XRGB8888 ||
> +                 plane->plane->formats[i] == DRM_FORMAT_ARGB8888 ||
> +                 plane->plane->formats[i] == DRM_FORMAT_RGBA8888 ||
> +                 plane->plane->formats[i] == DRM_FORMAT_NV12) {
> +                     *format = plane->plane->formats[i];
> +                     return 0;
> +             }
> +     }
> +     printf("No suitable formats found!\n");
> +     return -ENOENT;
> +}
> +
> +struct sp_dev *create_sp_dev(int card)
> +{
> +     struct sp_dev *dev;
> +     int ret, fd, i, j;
> +     drmModeRes *r = NULL;
> +     drmModePlaneRes *pr = NULL;
> +     char card_path[256];
> +
> +     snprintf(card_path, sizeof(card_path), "/dev/dri/card%d", card);
> +
> +     fd = open(card_path, O_RDWR);
> +     if (fd < 0) {
> +             printf("failed to open card0\n");
> +             return NULL;
> +     }
> +
> +     dev = calloc(1, sizeof(*dev));
> +     if (!dev) {
> +             printf("failed to allocate dev\n");
> +             return NULL;
> +     }
> +
> +     dev->fd = fd;
> +
> +     ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
> +     if (ret) {
> +             printf("failed to set client cap\n");
> +             goto err;
> +     }
> +
> +     ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1);
> +     if (ret) {
> +             printf("Failed to set atomic cap %d", ret);
> +             goto err;
> +     }
> +
> +     r = drmModeGetResources(dev->fd);
> +     if (!r) {
> +             printf("failed to get r\n");
> +             goto err;
> +     }
> +
> +     dev->num_connectors = r->count_connectors;
> +     dev->connectors = calloc(dev->num_connectors,
> +                             sizeof(struct sp_connector));
> +     if (!dev->connectors) {
> +             printf("failed to allocate connectors\n");
> +             goto err;
> +     }
> +     for (i = 0; i < dev->num_connectors; i++) {
> +             drmModeObjectPropertiesPtr props;
> +             dev->connectors[i].conn = drmModeGetConnector(dev->fd,
> +                                     r->connectors[i]);
> +             if (!dev->connectors[i].conn) {
> +                     printf("failed to get connector %d\n", i);
> +                     goto err;
> +             }
> +
> +             props = drmModeObjectGetProperties(dev->fd, r->connectors[i],
> +                             DRM_MODE_OBJECT_CONNECTOR);
> +             if (!props) {
> +                     printf("failed to get connector properties\n");
> +                     goto err;
> +             }
> +
> +             dev->connectors[i].crtc_id_pid = get_prop_id(dev, props,
> +                                                             "CRTC_ID");
> +             drmModeFreeObjectProperties(props);
> +             if (!dev->connectors[i].crtc_id_pid)
> +                     goto err;
> +     }
> +
> +     dev->num_encoders = r->count_encoders;
> +     dev->encoders = calloc(dev->num_encoders, sizeof(*dev->encoders));
> +     if (!dev->encoders) {
> +             printf("failed to allocate encoders\n");
> +             goto err;
> +     }
> +     for (i = 0; i < dev->num_encoders; i++) {
> +             dev->encoders[i] = drmModeGetEncoder(dev->fd, r->encoders[i]);
> +             if (!dev->encoders[i]) {
> +                     printf("failed to get encoder %d\n", i);
> +                     goto err;
> +             }
> +     }
> +
> +     dev->num_crtcs = r->count_crtcs;
> +     dev->crtcs = calloc(dev->num_crtcs, sizeof(struct sp_crtc));
> +     if (!dev->crtcs) {
> +             printf("failed to allocate crtcs\n");
> +             goto err;
> +     }
> +     for (i = 0; i < dev->num_crtcs; i++) {
> +             drmModeObjectPropertiesPtr props;
> +
> +             dev->crtcs[i].crtc = drmModeGetCrtc(dev->fd, r->crtcs[i]);
> +             if (!dev->crtcs[i].crtc) {
> +                     printf("failed to get crtc %d\n", i);
> +                     goto err;
> +             }
> +             dev->crtcs[i].pipe = i;
> +             dev->crtcs[i].num_planes = 0;
> +
> +             props = drmModeObjectGetProperties(dev->fd, r->crtcs[i],
> +                             DRM_MODE_OBJECT_CRTC);
> +             if (!props) {
> +                     printf("failed to get crtc properties\n");
> +                     goto err;
> +             }
> +
> +             dev->crtcs[i].mode_pid = get_prop_id(dev, props, "MODE_ID");
> +             dev->crtcs[i].active_pid = get_prop_id(dev, props, "ACTIVE");
> +             drmModeFreeObjectProperties(props);
> +             if (!dev->crtcs[i].mode_pid || !dev->crtcs[i].active_pid)
> +                     goto err;
> +     }
> +
> +     pr = drmModeGetPlaneResources(dev->fd);
> +     if (!pr) {
> +             printf("failed to get plane resources\n");
> +             goto err;
> +     }
> +     dev->num_planes = pr->count_planes;
> +     dev->planes = calloc(dev->num_planes, sizeof(struct sp_plane));
> +     for(i = 0; i < dev->num_planes; i++) {
> +             drmModeObjectPropertiesPtr props;
> +             struct sp_plane *plane = &dev->planes[i];
> +
> +             plane->dev = dev;
> +             plane->plane = drmModeGetPlane(dev->fd, pr->planes[i]);
> +             if (!plane->plane) {
> +                     printf("failed to get plane %d\n", i);
> +                     goto err;
> +             }
> +             plane->bo = NULL;
> +             plane->in_use = 0;
> +
> +             ret = get_supported_format(plane, &plane->format);
> +             if (ret) {
> +                     printf("failed to get supported format: %d\n", ret);
> +                     goto err;
> +             }
> +
> +             for (j = 0; j < dev->num_crtcs; j++) {
> +                     if (plane->plane->possible_crtcs & (1 << j))
> +                             dev->crtcs[j].num_planes++;
> +             }
> +
> +             props = drmModeObjectGetProperties(dev->fd, pr->planes[i],
> +                             DRM_MODE_OBJECT_PLANE);
> +             if (!props) {
> +                     printf("failed to get plane properties\n");
> +                     goto err;
> +             }
> +             plane->crtc_pid = get_prop_id(dev, props, "CRTC_ID");
> +             if (!plane->crtc_pid) {
> +                     drmModeFreeObjectProperties(props);
> +                     goto err;
> +             }
> +             plane->fb_pid = get_prop_id(dev, props, "FB_ID");
> +             if (!plane->fb_pid) {
> +                     drmModeFreeObjectProperties(props);
> +                     goto err;
> +             }
> +             plane->crtc_x_pid = get_prop_id(dev, props, "CRTC_X");
> +             if (!plane->crtc_x_pid) {
> +                     drmModeFreeObjectProperties(props);
> +                     goto err;
> +             }
> +             plane->crtc_y_pid = get_prop_id(dev, props, "CRTC_Y");
> +             if (!plane->crtc_y_pid) {
> +                     drmModeFreeObjectProperties(props);
> +                     goto err;
> +             }
> +             plane->crtc_w_pid = get_prop_id(dev, props, "CRTC_W");
> +             if (!plane->crtc_w_pid) {
> +                     drmModeFreeObjectProperties(props);
> +                     goto err;
> +             }
> +             plane->crtc_h_pid = get_prop_id(dev, props, "CRTC_H");
> +             if (!plane->crtc_h_pid) {
> +                     drmModeFreeObjectProperties(props);
> +                     goto err;
> +             }
> +             plane->src_x_pid = get_prop_id(dev, props, "SRC_X");
> +             if (!plane->src_x_pid) {
> +                     drmModeFreeObjectProperties(props);
> +                     goto err;
> +             }
> +             plane->src_y_pid = get_prop_id(dev, props, "SRC_Y");
> +             if (!plane->src_y_pid) {
> +                     drmModeFreeObjectProperties(props);
> +                     goto err;
> +             }
> +             plane->src_w_pid = get_prop_id(dev, props, "SRC_W");
> +             if (!plane->src_w_pid) {
> +                     drmModeFreeObjectProperties(props);
> +                     goto err;
> +             }
> +             plane->src_h_pid = get_prop_id(dev, props, "SRC_H");
> +             if (!plane->src_h_pid) {
> +                     drmModeFreeObjectProperties(props);
> +                     goto err;
> +             }
> +             drmModeFreeObjectProperties(props);
> +     }
> +
> +     if (pr)
> +             drmModeFreePlaneResources(pr);
> +     if (r)
> +             drmModeFreeResources(r);
> +
> +     return dev;
> +err:
> +     if (pr)
> +             drmModeFreePlaneResources(pr);
> +     if (r)
> +             drmModeFreeResources(r);
> +     destroy_sp_dev(dev);
> +     return NULL;
> +}
> +
> +void destroy_sp_dev(struct sp_dev *dev)
> +{
> +     int i;
> +
> +     if (dev->planes) {
> +             for (i = 0; i< dev->num_planes; i++) {
> +                     if (dev->planes[i].in_use)
> +                             put_sp_plane(&dev->planes[i]);
> +                     if (dev->planes[i].plane)
> +                             drmModeFreePlane(dev->planes[i].plane);
> +                     if (dev->planes[i].bo)
> +                             free_sp_bo(dev->planes[i].bo);
> +             }
> +             free(dev->planes);
> +     }
> +     if (dev->crtcs) {
> +             for (i = 0; i< dev->num_crtcs; i++) {
> +                     if (dev->crtcs[i].crtc)
> +                             drmModeFreeCrtc(dev->crtcs[i].crtc);
> +             }
> +             free(dev->crtcs);
> +     }
> +     if (dev->encoders) {
> +             for (i = 0; i< dev->num_encoders; i++) {
> +                     if (dev->encoders[i])
> +                             drmModeFreeEncoder(dev->encoders[i]);
> +             }
> +             free(dev->encoders);
> +     }
> +     if (dev->connectors) {
> +             for (i = 0; i< dev->num_connectors; i++) {
> +                     if (dev->connectors[i].conn)
> +                             drmModeFreeConnector(dev->connectors[i].conn);
> +             }
> +             free(dev->connectors);
> +     }
> +
> +     close(dev->fd);
> +     free(dev);
> +}
> diff --git a/tests/planetest/dev.h b/tests/planetest/dev.h
> new file mode 100644
> index 0000000..04dec79
> --- /dev/null
> +++ b/tests/planetest/dev.h
> @@ -0,0 +1,65 @@
> +#ifndef __DEV_H_INCLUDED__
> +#define __DEV_H_INCLUDED__
> +
> +#include <stdint.h>
> +#include <xf86drmMode.h>
> +
> +struct sp_bo;
> +struct sp_dev;
> +
> +struct sp_plane {
> +     struct sp_dev *dev;
> +     drmModePlanePtr plane;
> +     struct sp_bo *bo;
> +     int in_use;
> +     uint32_t format;
> +
> +     /* Property ID's */
> +     uint32_t crtc_pid;
> +     uint32_t fb_pid;
> +     uint32_t zpos_pid;
> +     uint32_t crtc_x_pid;
> +     uint32_t crtc_y_pid;
> +     uint32_t crtc_w_pid;
> +     uint32_t crtc_h_pid;
> +     uint32_t src_x_pid;
> +     uint32_t src_y_pid;
> +     uint32_t src_w_pid;
> +     uint32_t src_h_pid;
> +};
> +
> +struct sp_connector {
> +     drmModeConnectorPtr conn;
> +     uint32_t crtc_id_pid;
> +};
> +
> +struct sp_crtc {
> +     drmModeCrtcPtr crtc;
> +     int pipe;
> +     int num_planes;
> +     uint32_t mode_pid;
> +     uint32_t active_pid;
> +};
> +
> +struct sp_dev {
> +     int fd;
> +
> +     int num_connectors;
> +     struct sp_connector *connectors;
> +
> +     int num_encoders;
> +     drmModeEncoderPtr *encoders;
> +
> +     int num_crtcs;
> +     struct sp_crtc *crtcs;
> +
> +     int num_planes;
> +     struct sp_plane *planes;
> +};
> +
> +void parse_arguments(int argc, char *argv[], int *card, int *crtc);
> +
> +struct sp_dev *create_sp_dev(int card);
> +void destroy_sp_dev(struct sp_dev *dev);
> +
> +#endif /* __DEV_H_INCLUDED__ */
> diff --git a/tests/planetest/modeset.c b/tests/planetest/modeset.c
> new file mode 100644
> index 0000000..b8f6690
> --- /dev/null
> +++ b/tests/planetest/modeset.c
> @@ -0,0 +1,232 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include <xf86drm.h>
> +#include <xf86drmMode.h>
> +#include <drm_fourcc.h>
> +
> +#include "modeset.h"
> +#include "bo.h"
> +#include "dev.h"
> +
> +static int set_crtc_mode(struct sp_dev *dev, struct sp_crtc *crtc,
> +                     struct sp_connector *conn, drmModeModeInfoPtr mode)
> +{
> +     int ret;
> +     struct drm_mode_create_blob create_blob;
> +     drmModeAtomicReqPtr pset;
> +
> +     memset(&create_blob, 0, sizeof(create_blob));
> +     create_blob.length = sizeof(struct drm_mode_modeinfo);
> +     create_blob.data = (__u64)(uintptr_t)mode;
> +
> +     ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob);
> +     if (ret) {
> +             printf("Failed to create mode property blob %d", ret);
> +             return ret;
> +     }
> +
> +     pset = drmModeAtomicAlloc();
> +     if (!pset) {
> +             printf("Failed to allocate property set");
> +             return -1;
> +     }
> +
> +     ret = drmModeAtomicAddProperty(pset, crtc->crtc->crtc_id,
> +                                 crtc->mode_pid, create_blob.blob_id) ||
> +           drmModeAtomicAddProperty(pset, crtc->crtc->crtc_id,
> +                                 crtc->active_pid, 1) ||
> +           drmModeAtomicAddProperty(pset, conn->conn->connector_id,
> +                             conn->crtc_id_pid, crtc->crtc->crtc_id);
> +     if (ret) {
> +             printf("Failed to add blob %d to pset", create_blob.blob_id);
> +             drmModeAtomicFree(pset);
> +             return ret;
> +     }
> +
> +     ret = drmModeAtomicCommit(dev->fd, pset, DRM_MODE_ATOMIC_ALLOW_MODESET,
> +                                     NULL);
> +
> +     drmModeAtomicFree(pset);
> +
> +     if (ret) {
> +             printf("Failed to commit pset ret=%d\n", ret);
> +             return ret;
> +     }
> +
> +     memcpy(&crtc->crtc->mode, mode, sizeof(struct drm_mode_modeinfo));
> +     crtc->crtc->mode_valid = 1;
> +     return 0;
> +}
> +
> +int initialize_screens(struct sp_dev *dev)
> +{
> +     int ret, i, j;
> +     unsigned crtc_mask = 0;
> +
> +     for (i = 0; i < dev->num_connectors; i++) {
> +             struct sp_connector *c = &dev->connectors[i];
> +             drmModeModeInfoPtr m = NULL;
> +             drmModeEncoderPtr e = NULL;
> +             struct sp_crtc *cr = NULL;
> +
> +             if (c->conn->connection != DRM_MODE_CONNECTED)
> +                     continue;
> +
> +             if (!c->conn->count_modes) {
> +                     printf("connector has no modes, skipping\n");
> +                     continue;
> +             }
> +
> +             /* Take the first unless there's a preferred mode */
> +             m = &c->conn->modes[0];
> +             for (j = 0; j < c->conn->count_modes; j++) {
> +                     drmModeModeInfoPtr tmp_m = &c->conn->modes[j];
> +
> +                     if (!(tmp_m->type & DRM_MODE_TYPE_PREFERRED))
> +                             continue;
> +
> +                     m = tmp_m;
> +                     break;
> +             }
> +
> +             if (!c->conn->count_encoders) {
> +                     printf("no possible encoders for connector\n");
> +                     continue;
> +             }
> +
> +             for (j = 0; j < dev->num_encoders; j++) {
> +                     e = dev->encoders[j];
> +                     if (e->encoder_id == c->conn->encoders[0])
> +                             break;
> +             }
> +             if (j == dev->num_encoders) {
> +                     printf("could not find encoder for the connector\n");
> +                     continue;
> +             }
> +
> +             for (j = 0; j < dev->num_crtcs; j++) {
> +                     if ((1 << j) & crtc_mask)
> +                             continue;
> +
> +                     cr = &dev->crtcs[j];
> +
> +                     if ((1 << j) & e->possible_crtcs)
> +                             break;
> +             }
> +             if (j == dev->num_crtcs) {
> +                     printf("could not find crtc for the encoder\n");
> +                     continue;
> +             }
> +
> +             ret = set_crtc_mode(dev, cr, c, m);
> +             if (ret) {
> +                     printf("failed to set mode!\n");
> +                     continue;
> +             }
> +             crtc_mask |= 1 << j;
> +     }
> +     return 0;
> +}
> +
> +struct sp_plane *get_sp_plane(struct sp_dev *dev, struct sp_crtc *crtc)
> +{
> +     int i;
> +
> +     for(i = 0; i < dev->num_planes; i++) {
> +             struct sp_plane *p = &dev->planes[i];
> +
> +             if (p->in_use)
> +                     continue;
> +
> +             if (!(p->plane->possible_crtcs & (1 << crtc->pipe)))
> +                     continue;
> +
> +             p->in_use = 1;
> +             return p;
> +     }
> +     return NULL;
> +}
> +
> +void put_sp_plane(struct sp_plane *plane)
> +{
> +     drmModePlanePtr p;
> +
> +     /* Get the latest plane information (most notably the crtc_id) */
> +     p = drmModeGetPlane(plane->dev->fd, plane->plane->plane_id);
> +     if (p)
> +             plane->plane = p;
> +
> +     if (plane->bo) {
> +             free_sp_bo(plane->bo);
> +             plane->bo = NULL;
> +     }
> +     plane->in_use = 0;
> +}
> +
> +int set_sp_plane(struct sp_dev *dev, struct sp_plane *plane,
> +             struct sp_crtc *crtc, int x, int y)
> +{
> +     int ret;
> +     uint32_t w, h;
> +
> +     w = plane->bo->width;
> +     h = plane->bo->height;
> +
> +     if ((w + x) > crtc->crtc->mode.hdisplay)
> +             w = crtc->crtc->mode.hdisplay - x;
> +     if ((h + y) > crtc->crtc->mode.vdisplay)
> +             h = crtc->crtc->mode.vdisplay - y;
> +
> +     ret = drmModeSetPlane(dev->fd, plane->plane->plane_id,
> +                     crtc->crtc->crtc_id, plane->bo->fb_id, 0, x, y, w, h,
> +                     0, 0, w << 16, h << 16);
> +     if (ret) {
> +             printf("failed to set plane to crtc ret=%d\n", ret);
> +             return ret;
> +     }
> +
> +     return ret;
> +}
> +int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane,
> +             drmModeAtomicReqPtr pset, struct sp_crtc *crtc, int x, int y)
> +{
> +     int ret;
> +     uint32_t w, h;
> +
> +     w = plane->bo->width;
> +     h = plane->bo->height;
> +
> +     if ((w + x) > crtc->crtc->mode.hdisplay)
> +             w = crtc->crtc->mode.hdisplay - x;
> +     if ((h + y) > crtc->crtc->mode.vdisplay)
> +             h = crtc->crtc->mode.vdisplay - y;
> +
> +     ret = drmModeAtomicAddProperty(pset, plane->plane->plane_id,
> +                     plane->crtc_pid, crtc->crtc->crtc_id)
> +             || drmModeAtomicAddProperty(pset, plane->plane->plane_id,
> +                     plane->fb_pid, plane->bo->fb_id)
> +             || drmModeAtomicAddProperty(pset, plane->plane->plane_id,
> +                     plane->crtc_x_pid, x)
> +             || drmModeAtomicAddProperty(pset, plane->plane->plane_id,
> +                     plane->crtc_y_pid, y)
> +             || drmModeAtomicAddProperty(pset, plane->plane->plane_id,
> +                     plane->crtc_w_pid, w)
> +             || drmModeAtomicAddProperty(pset, plane->plane->plane_id,
> +                     plane->crtc_h_pid, h)
> +             || drmModeAtomicAddProperty(pset, plane->plane->plane_id,
> +                     plane->src_x_pid, 0)
> +             || drmModeAtomicAddProperty(pset, plane->plane->plane_id,
> +                     plane->src_y_pid, 0)
> +             || drmModeAtomicAddProperty(pset, plane->plane->plane_id,
> +                     plane->src_w_pid, w << 16)
> +             || drmModeAtomicAddProperty(pset, plane->plane->plane_id,
> +                     plane->src_h_pid, h << 16);
> +     if (ret) {
> +             printf("failed to add properties to the set\n");
> +             return -1;
> +     }
> +
> +     return ret;
> +}
> diff --git a/tests/planetest/modeset.h b/tests/planetest/modeset.h
> new file mode 100644
> index 0000000..5499959
> --- /dev/null
> +++ b/tests/planetest/modeset.h
> @@ -0,0 +1,19 @@
> +#ifndef __MODESET_H_INCLUDED__
> +#define __MODESET_H_INCLUDED__
> +
> +struct sp_dev;
> +struct sp_crtc;
> +
> +int initialize_screens(struct sp_dev *dev);
> +
> +
> +struct sp_plane *get_sp_plane(struct sp_dev *dev, struct sp_crtc *crtc);
> +void put_sp_plane(struct sp_plane *plane);
> +
> +int set_sp_plane(struct sp_dev *dev, struct sp_plane *plane,
> +             struct sp_crtc *crtc, int x, int y);
> +
> +int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane,
> +             drmModeAtomicReqPtr pset, struct sp_crtc *crtc, int x, int y);
> +
> +#endif /* __MODESET_H_INCLUDED__ */
> diff --git a/tests/planetest/planetest.c b/tests/planetest/planetest.c
> new file mode 100644
> index 0000000..5e187c9
> --- /dev/null
> +++ b/tests/planetest/planetest.c
> @@ -0,0 +1,116 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/select.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <signal.h>
> +#include <time.h>
> +#include <errno.h>
> +
> +#include <xf86drm.h>
> +
> +#include "dev.h"
> +#include "bo.h"
> +#include "modeset.h"
> +
> +static int terminate = 0;
> +
> +static void sigint_handler(int arg)
> +{
> +     terminate = 1;
> +}
> +
> +static void incrementor(int *inc, int *val, int increment, int lower, int 
> upper)
> +{
> +     if(*inc > 0)
> +             *inc = *val + increment >= upper ? -1 : 1;
> +     else
> +             *inc = *val - increment <= lower ? 1 : -1;
> +     *val += *inc * increment;
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +     int ret, i, j, num_test_planes;
> +     int x_inc = 1, x = 0, y_inc = 1, y = 0;
> +     uint32_t plane_w = 128, plane_h = 128;
> +     struct sp_dev *dev;
> +     struct sp_plane **plane = NULL;
> +     struct sp_crtc *test_crtc;
> +     int card = 0, crtc = 0;
> +
> +     signal(SIGINT, sigint_handler);
> +
> +     parse_arguments(argc, argv, &card, &crtc);
> +
> +     dev = create_sp_dev(card);
> +     if (!dev) {
> +             printf("Failed to create sp_dev\n");
> +             return -1;
> +     }
> +
> +     if (crtc >= dev->num_crtcs) {
> +             printf("Invalid crtc %d (num=%d)\n", crtc, dev->num_crtcs);
> +             return -1;
> +     }
> +
> +     ret = initialize_screens(dev);
> +     if (ret) {
> +             printf("Failed to initialize screens\n");
> +             goto out;
> +     }
> +     test_crtc = &dev->crtcs[crtc];
> +
> +     plane = calloc(dev->num_planes, sizeof(*plane));
> +     if (!plane) {
> +             printf("Failed to allocate plane array\n");
> +             goto out;
> +     }
> +
> +     /* Create our planes */
> +     num_test_planes = test_crtc->num_planes;
> +     for (i = 0; i < num_test_planes; i++) {
> +             plane[i] = get_sp_plane(dev, test_crtc);
> +             if (!plane[i]) {
> +                     printf("no unused planes available\n");
> +                     goto out;
> +             }
> +
> +             plane[i]->bo = create_sp_bo(dev, plane_w, plane_h, 16,
> +                             plane[i]->format, 0);
> +             if (!plane[i]->bo) {
> +                     printf("failed to create plane bo\n");
> +                     goto out;
> +             }
> +
> +             fill_bo(plane[i]->bo, 0xFF, 0xFF, 0xFF, 0xFF);
> +     }
> +
> +     while (!terminate) {
> +             incrementor(&x_inc, &x, 5, 0,
> +                     test_crtc->crtc->mode.hdisplay - plane_w);
> +             incrementor(&y_inc, &y, 5, 0, test_crtc->crtc->mode.vdisplay -
> +                                             plane_h * num_test_planes);
> +
> +             for (j = 0; j < num_test_planes; j++) {
> +                     ret = set_sp_plane(dev, plane[j], test_crtc,
> +                                     x, y + j * plane_h);
> +                     if (ret) {
> +                             printf("failed to set plane %d %d\n", j, ret);
> +                             goto out;
> +                     }
> +             }
> +             usleep(15 * 1000);
> +     }
> +
> +     for (i = 0; i < num_test_planes; i++)
> +             put_sp_plane(plane[i]);
> +
> +out:
> +     destroy_sp_dev(dev);
> +     free(plane);
> +     return ret;
> +}
> -- 
> 2.7.4
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to