From patchwork Thu Dec 15 04:28:33 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 5744 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id C134323E04 for ; Thu, 15 Dec 2011 04:28:36 +0000 (UTC) Received: from mail-ey0-f180.google.com (mail-ey0-f180.google.com [209.85.215.180]) by fiordland.canonical.com (Postfix) with ESMTP id B7C19A1811B for ; Thu, 15 Dec 2011 04:28:36 +0000 (UTC) Received: by mail-ey0-f180.google.com with SMTP id k10so1643784eaa.11 for ; Wed, 14 Dec 2011 20:28:36 -0800 (PST) Received: by 10.204.133.213 with SMTP id g21mr315600bkt.126.1323923316476; Wed, 14 Dec 2011 20:28:36 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.205.129.2 with SMTP id hg2cs28590bkc; Wed, 14 Dec 2011 20:28:36 -0800 (PST) Received: by 10.236.73.230 with SMTP id v66mr2129188yhd.61.1323923314429; Wed, 14 Dec 2011 20:28:34 -0800 (PST) Received: from mail-yw0-f50.google.com (mail-yw0-f50.google.com [209.85.213.50]) by mx.google.com with ESMTPS id c20si902801anj.17.2011.12.14.20.28.34 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 14 Dec 2011 20:28:34 -0800 (PST) Received-SPF: pass (google.com: domain of robdclark@gmail.com designates 209.85.213.50 as permitted sender) client-ip=209.85.213.50; Authentication-Results: mx.google.com; spf=pass (google.com: domain of robdclark@gmail.com designates 209.85.213.50 as permitted sender) smtp.mail=robdclark@gmail.com; dkim=pass (test mode) header.i=@gmail.com Received: by yhoo22 with SMTP id o22so2070220yho.37 for ; Wed, 14 Dec 2011 20:28:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=Lcdbf5z/JydDFDy4k4YD1FZNqtuFRxQIFH+iut3CJH8=; b=DT3GYKBBQNt1pnfXAUQTN9OIGQVKr24cNlzx19uGDoK9pJs4e3/a08u48ArCOkE13s aSet7FTkoH4Zv9TI+tdBfOGu6maiUnVRMXIGeolCIihpNHNySjqBQ9DNWXgk0t3WviRS xLG11KQQHtmZ72zbvnkAcqyb+x3161jc+6Qrs= Received: by 10.236.77.72 with SMTP id c48mr2129872yhe.55.1323923313917; Wed, 14 Dec 2011 20:28:33 -0800 (PST) Received: from localhost (ppp-70-253-156-7.dsl.rcsntx.swbell.net. [70.253.156.7]) by mx.google.com with ESMTPS id i22sm7002582yhm.10.2011.12.14.20.28.32 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 14 Dec 2011 20:28:33 -0800 (PST) Sender: Rob Clark From: Rob Clark To: dri-devel@lists.freedesktop.org Cc: patches@linaro.org, Rob Clark Subject: [PATCH 2/2] modetest: add YUV and multi-planar support Date: Wed, 14 Dec 2011 22:28:33 -0600 Message-Id: <1323923313-4231-2-git-send-email-rob.clark@linaro.org> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1323923313-4231-1-git-send-email-rob.clark@linaro.org> References: <1323923313-4231-1-git-send-email-rob.clark@linaro.org> From: Rob Clark Signed-off-by: Rob Clark --- This one is a bit f-ugly.. kms_bo_create() and dumb-scanout alloc only really knows about allocating 4byte/pixel buffers, so we just allocate oversized buffers and use the part we need. It is functional enough to test the driver (or at least omapdrm), but I'm not sure about how best to deal w/ kms_bo_create(). (Or perhaps I should only test YUV support in omapdrmtest tree, and not try to use generic kms_bo_create()?) tests/modetest/modetest.c | 151 ++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 142 insertions(+), 9 deletions(-) diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c index 2936de0..36bdfff 100644 --- a/tests/modetest/modetest.c +++ b/tests/modetest/modetest.c @@ -335,6 +335,7 @@ struct plane { uint32_t con_id; /* the id of connector to bind to */ uint32_t w, h; unsigned int fb_id; + char format_str[5]; /* need to leave room for terminating \0 */ }; static void @@ -594,6 +595,63 @@ page_flip_handler(int fd, unsigned int frame, } } +/* swap these for big endian.. */ +#define RED 2 +#define GREEN 1 +#define BLUE 0 + +static void +fill420(unsigned char *y, unsigned char *u, unsigned char *v, + int cs /*chroma pixel stride */, + int n, int width, int height, int stride) +{ + 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; + } + } +} + +static void +fill422(unsigned char *virtual, int n, int width, int height, int stride) +{ + 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; + } + } +} + static int set_plane(struct kms_driver *kms, struct connector *c, struct plane *p) { @@ -602,8 +660,8 @@ set_plane(struct kms_driver *kms, struct connector *c, struct plane *p) 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; - int i, crtc_x, crtc_y, crtc_w, crtc_h; + uint32_t plane_flags = 0, format; + int i, ret, crtc_x, crtc_y, crtc_w, crtc_h; /* find an unused plane which can be connected to our crtc */ plane_resources = drmModeGetPlaneResources(fd); @@ -627,19 +685,87 @@ set_plane(struct kms_driver *kms, struct connector *c, struct plane *p) 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; } - /* TODO.. would be nice to test YUV overlays.. */ - if (create_test_buffer(kms, p->w, p->h, &pitches[0], &plane_bo)) - 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; - kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]); + 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[1]); + + fill420(virtual, virtual+offsets[1], virtual+offsets[2], + 1, 0, p->w, p->h, pitches[0]); + + format = DRM_FORMAT_YVU420; + } 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, DRM_FORMAT_XRGB8888, + 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; @@ -826,6 +952,7 @@ void usage(char *name) fprintf(stderr, "\t-s :\tset a mode\n"); fprintf(stderr, "\t-s @:\tset a mode\n"); fprintf(stderr, "\t-P :x\tset a plane\n"); + fprintf(stderr, "\t-P :x@\tset a plane\n"); fprintf(stderr, "\n\tDefault is to dump all info.\n"); exit(0); } @@ -862,7 +989,7 @@ int main(int argc, char **argv) char *modeset = NULL; int i, count = 0, plane_count = 0; struct connector con_args[2]; - struct plane plane_args[2]; + struct plane plane_args[2] = {0}; opterr = 0; while ((c = getopt(argc, argv, optstr)) != -1) { @@ -900,7 +1027,13 @@ int main(int argc, char **argv) count++; break; case 'P': - if (sscanf(optarg, "%d:%dx%d", + 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)