From patchwork Wed Nov 15 09:00:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 10059015 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B0D49601D3 for ; Wed, 15 Nov 2017 09:00:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A0A4D28B13 for ; Wed, 15 Nov 2017 09:00:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9274429DE0; Wed, 15 Nov 2017 09:00:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 80D6F28B13 for ; Wed, 15 Nov 2017 09:00:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755691AbdKOJAC (ORCPT ); Wed, 15 Nov 2017 04:00:02 -0500 Received: from galahad.ideasonboard.com ([185.26.127.97]:33199 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751617AbdKOJAB (ORCPT ); Wed, 15 Nov 2017 04:00:01 -0500 Received: from avalon.ideasonboard.com (unknown [182.232.36.108]) by galahad.ideasonboard.com (Postfix) with ESMTPSA id E7C36201C5; Wed, 15 Nov 2017 09:58:39 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1510736322; bh=leVGxqjVDcgdyHKhvQKvbaIm0RIxcYxTYtH0aQaRU7I=; h=From:To:Cc:Subject:Date:From; b=IUJvieqz3l8Vj51YJIEGyuije5S8XDYEBiPSDON1MPj8BHidgH3XF75fmV15ujcto I4Q6w7ZWmQ+YcJ5uobM/xCpDQNZKLL6dVFaQPIyhAsZk7Ct51LM4IpRb8CFMAMLKj5 0P4LxGclyACq//bWgF1QOWT4++u+K5gong85ZJbI= From: Laurent Pinchart To: linux-renesas-soc@vger.kernel.org Cc: Andrzej Hajda Subject: [PATCH] v4l2-drm-example: Make the exporter selectable Date: Wed, 15 Nov 2017 11:00:01 +0200 Message-Id: <20171115090001.3005-1-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.13.6 Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The new -e command line option allows selecting the exporter between the V4L2 and DRM side. DRM is used as the exporter by default. Signed-off-by: Laurent Pinchart --- v4l2-drm-example/dmabuf-sharing.c | 99 +++++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 10 deletions(-) This patch is against the master branch of git://git.infradead.org/users/kmpark/public-apps and is available in my clone tree at git://git.ideasonboard.org/samsung-public-apps.git. Andrzej, if the patch is acceptable, could you merge it upstream ? diff --git a/v4l2-drm-example/dmabuf-sharing.c b/v4l2-drm-example/dmabuf-sharing.c index 5e1fb6a8f0c3..e2f1a4228af8 100644 --- a/v4l2-drm-example/dmabuf-sharing.c +++ b/v4l2-drm-example/dmabuf-sharing.c @@ -69,6 +69,11 @@ static inline int warn(const char *file, int line, const char *fmt, ...) #define WARN_ON(cond, ...) \ ((cond) ? warn(__FILE__, __LINE__, __VA_ARGS__) : 0) +enum dmabuf_exporter { + DMABUF_EXPORTER_DRM = 0, + DMABUF_EXPORTER_V4L2, +}; + struct setup { char module[32]; int conId; @@ -85,6 +90,7 @@ struct setup { unsigned int use_compose : 1; struct v4l2_rect crop; struct v4l2_rect compose; + enum dmabuf_exporter exporter; }; struct drm_device { @@ -105,10 +111,12 @@ struct drm_device { unsigned int height; struct v4l2_rect compose; + int export; }; struct v4l2_device { const char *devname; + enum v4l2_memory memory; int fd; struct v4l2_pix_format format; @@ -149,6 +157,7 @@ static void usage(char *name) fprintf(stderr, "\nGeneric options:\n\n"); fprintf(stderr, "\t-b buffer_count\tset number of buffers\n"); + fprintf(stderr, "\t-e \tset the exporter ('v4l2' or 'drm')\n"); fprintf(stderr, "\t-h\tshow this help\n"); } @@ -170,13 +179,21 @@ static int parse_args(int argc, char *argv[], struct setup *s) strcpy(s->video, "/dev/video0"); - while ((c = getopt(argc, argv, "b:F:f:hi:M:o:p:S:s:t:")) != -1) { + while ((c = getopt(argc, argv, "b:e:F:f:hi:M:o:p:S:s:t:")) != -1) { switch (c) { case 'b': ret = sscanf(optarg, "%u", &s->buffer_count); if (WARN_ON(ret != 1, "incorrect buffer count\n")) return -1; break; + case 'e': + if (strcmp(optarg, "v4l2") == 0) + s->exporter = DMABUF_EXPORTER_V4L2; + else if (strcmp(optarg, "drm") == 0) + s->exporter = DMABUF_EXPORTER_DRM; + else if (WARN_ON(1, "")) + return -1; + break; case 'F': if (WARN_ON(strlen(optarg) != 4, "invalid fourcc\n")) return -1; @@ -284,13 +301,49 @@ fail_prime: fail_gem: memset(&gem_destroy, 0, sizeof gem_destroy); - gem_destroy.handle = b->bo_handle, + gem_destroy.handle = b->bo_handle; ret = ioctl(dev->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &gem_destroy); WARN_ON(ret, "DESTROY_DUMB failed: %s\n", ERRSTR); return -1; } +static int drm_buffer_import(struct drm_device *dev, struct buffer *b, + const struct v4l2_pix_format *fmt) +{ + struct drm_prime_handle prime; + struct drm_gem_close gem_close; + int ret; + + memset(&prime, 0, sizeof prime); + prime.fd = b->dbuf_fd; + ret = ioctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime); + if (WARN_ON(ret, "PRIME_FD_TO_HANDLE failed: %s\n", ERRSTR)) + return -1; + b->bo_handle = prime.handle; + + uint32_t offsets[4] = { 0 }; + uint32_t pitches[4] = { fmt->bytesperline }; + uint32_t bo_handles[4] = { b->bo_handle }; + unsigned int fourcc = dev->format; + if (!fourcc) + fourcc = fmt->pixelformat; + ret = drmModeAddFB2(dev->fd, fmt->width, fmt->height, fourcc, bo_handles, + pitches, offsets, &b->fb_handle, 0); + if (WARN_ON(ret, "drmModeAddFB2 failed: %s\n", ERRSTR)) + goto fail_gem; + + return 0; + +fail_gem: + memset(&gem_close, 0, sizeof gem_close); + gem_close.handle = b->bo_handle; + ret = ioctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &gem_close); + WARN_ON(ret, "GEM_CLOSE failed: %s\n", ERRSTR); + + return -1; +} + static int drm_find_crtc(struct drm_device *dev) { int ret = -1; @@ -406,8 +459,13 @@ static void drm_init(struct drm_device *dev, const struct v4l2_pix_format *fmt, /* TODO: add support for multiplanar formats */ for (unsigned int i = 0; i < num_buffers; ++i) { - ret = drm_buffer_create(dev, &buffers[i], fmt); - BYE_ON(ret, "failed to create buffer%d\n", i); + if (dev->export) { + ret = drm_buffer_create(dev, &buffers[i], fmt); + BYE_ON(ret, "failed to create buffer%d\n", i); + } else { + ret = drm_buffer_import(dev, &buffers[i], fmt); + BYE_ON(ret, "failed to import buffer%d\n", i); + } } printf("buffers ready\n"); @@ -452,7 +510,8 @@ static void drm_page_flip(struct drm_device *dev, struct buffer *buffer) } } -static void v4l2_init(struct v4l2_device *dev, unsigned int num_buffers) +static void v4l2_init(struct v4l2_device *dev, unsigned int num_buffers, + struct buffer *buffers) { int ret; @@ -494,7 +553,7 @@ static void v4l2_init(struct v4l2_device *dev, unsigned int num_buffers) memset(&rqbufs, 0, sizeof(rqbufs)); rqbufs.count = num_buffers; rqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - rqbufs.memory = V4L2_MEMORY_DMABUF; + rqbufs.memory = dev->memory; ret = ioctl(dev->fd, VIDIOC_REQBUFS, &rqbufs); BYE_ON(ret < 0, "VIDIOC_REQBUFS failed: %s\n", ERRSTR); @@ -502,6 +561,22 @@ static void v4l2_init(struct v4l2_device *dev, unsigned int num_buffers) "%u of %u buffers\n", rqbufs.count, num_buffers); dev->format = fmt.fmt.pix; + + if (dev->memory == V4L2_MEMORY_DMABUF) + return; + + for (unsigned int i = 0; i < num_buffers; ++i) { + struct v4l2_exportbuffer expbuf; + memset(&expbuf, 0, sizeof(expbuf)); + expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + expbuf.index = i; + + ret = ioctl(dev->fd, VIDIOC_EXPBUF, &expbuf); + BYE_ON(ret < 0, "VIDIOC_EXPBUF failed: %s\n", ERRSTR); + buffers[i].dbuf_fd = expbuf.fd; + + printf("dbuf_fd = %d\n", expbuf.fd); + } } static void v4l2_queue_buffer(struct v4l2_device *dev, const struct buffer *buffer) @@ -511,9 +586,10 @@ static void v4l2_queue_buffer(struct v4l2_device *dev, const struct buffer *buff memset(&buf, 0, sizeof buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_DMABUF; + buf.memory = dev->memory; buf.index = buffer->index; - buf.m.fd = buffer->dbuf_fd; + if (dev->memory == V4L2_MEMORY_DMABUF) + buf.m.fd = buffer->dbuf_fd; ret = ioctl(dev->fd, VIDIOC_QBUF, &buf); BYE_ON(ret, "VIDIOC_QBUF(index = %d) failed: %s\n", buffer->index, ERRSTR); @@ -562,6 +638,8 @@ int main(int argc, char *argv[]) memset(&v4l2, 0, sizeof v4l2); v4l2.devname = s.video; + v4l2.memory = s.exporter == DMABUF_EXPORTER_V4L2 + ? V4L2_MEMORY_MMAP : V4L2_MEMORY_DMABUF; if (s.use_wh) { v4l2.format.width = s.w; @@ -570,13 +648,13 @@ int main(int argc, char *argv[]) if (s.in_fourcc) v4l2.format.pixelformat = s.in_fourcc; - v4l2_init(&v4l2, s.buffer_count); - struct buffer buffers[s.buffer_count]; for (unsigned int i = 0; i < s.buffer_count; ++i) buffers[i].index = i; + v4l2_init(&v4l2, s.buffer_count, buffers); + memset(&drm, 0, sizeof drm); drm.module = s.module; drm.modestr = s.modestr; @@ -585,6 +663,7 @@ int main(int argc, char *argv[]) drm.height = v4l2.format.height; drm.crtc_id = s.crtId; drm.con_id = s.conId; + drm.export = s.exporter == DMABUF_EXPORTER_DRM; drm_init(&drm, &v4l2.format, s.buffer_count, buffers);