Patch Detail
Show a patch.
GET /api/patches/17017/?format=api
{ "id": 17017, "url": "https://patchwork.libcamera.org/api/patches/17017/?format=api", "web_url": "https://patchwork.libcamera.org/patch/17017/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20220807180100.396-4-laurent.pinchart@ideasonboard.com>", "date": "2022-08-07T18:01:00", "name": "[libcamera-devel,3/3] cam: kms_sink: Scale the frame buffer to full screen if supported", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "3514a491bbfc9c7fd0ad3421be76c65fc5d4d369", "submitter": { "id": 2, "url": "https://patchwork.libcamera.org/api/people/2/?format=api", "name": "Laurent Pinchart", "email": "laurent.pinchart@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/17017/mbox/", "series": [ { "id": 3384, "url": "https://patchwork.libcamera.org/api/series/3384/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3384", "date": "2022-08-07T18:00:57", "name": "cam: Support KMS scaling", "version": 1, "mbox": "https://patchwork.libcamera.org/series/3384/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/17017/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/17017/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id B6F50C3272\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSun, 7 Aug 2022 18:01:17 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 793CF6332C;\n\tSun, 7 Aug 2022 20:01:17 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 496ED6332B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 7 Aug 2022 20:01:14 +0200 (CEST)", "from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id DA63F749;\n\tSun, 7 Aug 2022 20:01:13 +0200 (CEST)" ], "DKIM-Signature": [ "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1659895277;\n\tbh=Dm1ig5xeC1QUDBLV1JhWKZs9FDz9jlFFiDVsAReKptI=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=KvgwVWjqZI3+yAHgNmf7n4LWPN8RmRhaMVpdmjsLDsPOn1vG2LPO4OePMiPqOYJa4\n\tSxrfc+nkVIBMJgcKG0BbVhQIuvc1ElHsAH1AI3SwgCf0rAGqkTnnjRYSo/VUvI+2P/\n\tthbYdPj6FGLF4xPOct7SWvCQDSZf9DjsxNwpgIxzPnzb4F12cXsxmkrsNEdu+iwCXT\n\t+J6SjaYhuc/qtrQMZFK8/9fvTeLLeOpBC+e+HIcPXEcjrt+W8I2UaIMhfS7AqyWAVF\n\tR64fEaAS8Ajh0lWw7gM8QOd9Jbpq6bwNUea4Mdae7fyLD/QuFrNjbVWJMLMHd4icwi\n\tXh1E9wv4aZt4A==", "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1659895274;\n\tbh=Dm1ig5xeC1QUDBLV1JhWKZs9FDz9jlFFiDVsAReKptI=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=TvqwyJRgj+WpNTcDJCXMTAYikXzysfmT7hAU5mGWAwqxaJ6jLXNm+fQLsP9IkdIDw\n\ttVPhr9LLcyp8sNQTj1FOSaomqVmpEWXw+yqePpFepiOodz45vIhNEJ05iyf03vNTZo\n\thhracaDpH9DIQu8/mIMfYDTNlxJq+NsJdNyDGgIA=" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"TvqwyJRg\"; dkim-atps=neutral", "To": "libcamera-devel@lists.libcamera.org", "Date": "Sun, 7 Aug 2022 21:01:00 +0300", "Message-Id": "<20220807180100.396-4-laurent.pinchart@ideasonboard.com>", "X-Mailer": "git-send-email 2.35.1", "In-Reply-To": "<20220807180100.396-1-laurent.pinchart@ideasonboard.com>", "References": "<20220807180100.396-1-laurent.pinchart@ideasonboard.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH 3/3] cam: kms_sink: Scale the frame buffer\n\tto full screen if supported", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "From": "Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>", "Reply-To": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "The KMS sink currently displays the frame buffer on the top-left corner\nof the screen, resulting in either a black area on the bottom and right\nsides (if the frame buffer is smaller than the display resolution) of in\na restricted field of view (if the frame buffer is larger than the\ndisplay resolution). Improve this by scaling the frame buffer to full\nscreen if supported, and aligning the crop rectangle to the frame buffer\ncenter if the field of view needs to be restricted.\n\nThe implementation test three possible composition options, from best to\nworst. The tests are performed when the camera is started, as testing\natomic commits requires access to frame buffer objects, which are not\navailable at configure time. Changing this would require either a large\nrefactoring of the cam application to provide frame buffers earlier, or\nextending the KMS API to support testing commits with dummy buffer\nobjects. Both are candidates for later development.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/cam/kms_sink.cpp | 92 ++++++++++++++++++++++++++++++++++++++++----\n src/cam/kms_sink.h | 8 ++++\n 2 files changed, 92 insertions(+), 8 deletions(-)", "diff": "diff --git a/src/cam/kms_sink.cpp b/src/cam/kms_sink.cpp\nindex 16435ede6b6a..2f306955cf51 100644\n--- a/src/cam/kms_sink.cpp\n+++ b/src/cam/kms_sink.cpp\n@@ -284,6 +284,77 @@ int KMSSink::stop()\n \treturn FrameSink::stop();\n }\n \n+bool KMSSink::testModeSet(DRM::FrameBuffer *drmBuffer,\n+\t\t\t const libcamera::Rectangle &src,\n+\t\t\t const libcamera::Rectangle &dst)\n+{\n+\tDRM::AtomicRequest drmRequest{ &dev_ };\n+\n+\tdrmRequest.addProperty(connector_, \"CRTC_ID\", crtc_->id());\n+\n+\tdrmRequest.addProperty(crtc_, \"ACTIVE\", 1);\n+\tdrmRequest.addProperty(crtc_, \"MODE_ID\", mode_->toBlob(&dev_));\n+\n+\tdrmRequest.addProperty(plane_, \"CRTC_ID\", crtc_->id());\n+\tdrmRequest.addProperty(plane_, \"FB_ID\", drmBuffer->id());\n+\tdrmRequest.addProperty(plane_, \"SRC_X\", src.x << 16);\n+\tdrmRequest.addProperty(plane_, \"SRC_Y\", src.y << 16);\n+\tdrmRequest.addProperty(plane_, \"SRC_W\", src.width << 16);\n+\tdrmRequest.addProperty(plane_, \"SRC_H\", src.height << 16);\n+\tdrmRequest.addProperty(plane_, \"CRTC_X\", dst.x);\n+\tdrmRequest.addProperty(plane_, \"CRTC_Y\", dst.y);\n+\tdrmRequest.addProperty(plane_, \"CRTC_W\", dst.width);\n+\tdrmRequest.addProperty(plane_, \"CRTC_H\", dst.height);\n+\n+\treturn !drmRequest.commit(DRM::AtomicRequest::FlagAllowModeset |\n+\t\t\t\t DRM::AtomicRequest::FlagTestOnly);\n+}\n+\n+bool KMSSink::setupComposition(DRM::FrameBuffer *drmBuffer)\n+{\n+\t/*\n+\t * Test composition options, from most to least desirable, to select the\n+\t * best one.\n+\t */\n+\tconst libcamera::Rectangle framebuffer{ size_ };\n+\tconst libcamera::Rectangle display{ 0, 0, mode_->hdisplay, mode_->vdisplay };\n+\n+\t/* 1. Scale the frame buffer to full screen. */\n+\tlibcamera::Rectangle src = libcamera::Rectangle{ size_ };\n+\tlibcamera::Rectangle dst = display;\n+\n+\tif (testModeSet(drmBuffer, src, dst)) {\n+\t\tstd::cout << \"KMS: full-screen scaled output\" << std::endl;\n+\t\tsrc_ = src;\n+\t\tdst_ = dst;\n+\t\treturn true;\n+\t}\n+\n+\t/* 2. Center the frame buffer on the display. */\n+\tsrc = display.size().centeredTo(framebuffer.center()).boundedTo(framebuffer);\n+\tdst = framebuffer.size().centeredTo(display.center()).boundedTo(display);\n+\n+\tif (testModeSet(drmBuffer, src, dst)) {\n+\t\tstd::cout << \"KMS: centered output\" << std::endl;\n+\t\tsrc_ = src;\n+\t\tdst_ = dst;\n+\t\treturn true;\n+\t}\n+\n+\t/* 3. Align the frame buffer on the top-left of the display. */\n+\tsrc = framebuffer.boundedTo(display);\n+\tdst = display.boundedTo(framebuffer);\n+\n+\tif (testModeSet(drmBuffer, src, dst)) {\n+\t\tstd::cout << \"KMS: top-left aligned output\" << std::endl;\n+\t\tsrc_ = src;\n+\t\tdst_ = dst;\n+\t\treturn true;\n+\t}\n+\n+\treturn false;\n+}\n+\n bool KMSSink::processRequest(libcamera::Request *camRequest)\n {\n \t/*\n@@ -307,20 +378,25 @@ bool KMSSink::processRequest(libcamera::Request *camRequest)\n \n \tif (!active_ && !queued_) {\n \t\t/* Enable the display pipeline on the first frame. */\n+\t\tif (!setupComposition(drmBuffer)) {\n+\t\t\tstd::cerr << \"Failed to setup composition\" << std::endl;\n+\t\t\treturn true;\n+\t\t}\n+\n \t\tdrmRequest->addProperty(connector_, \"CRTC_ID\", crtc_->id());\n \n \t\tdrmRequest->addProperty(crtc_, \"ACTIVE\", 1);\n \t\tdrmRequest->addProperty(crtc_, \"MODE_ID\", mode_->toBlob(&dev_));\n \n \t\tdrmRequest->addProperty(plane_, \"CRTC_ID\", crtc_->id());\n-\t\tdrmRequest->addProperty(plane_, \"SRC_X\", 0 << 16);\n-\t\tdrmRequest->addProperty(plane_, \"SRC_Y\", 0 << 16);\n-\t\tdrmRequest->addProperty(plane_, \"SRC_W\", size_.width << 16);\n-\t\tdrmRequest->addProperty(plane_, \"SRC_H\", size_.height << 16);\n-\t\tdrmRequest->addProperty(plane_, \"CRTC_X\", 0);\n-\t\tdrmRequest->addProperty(plane_, \"CRTC_Y\", 0);\n-\t\tdrmRequest->addProperty(plane_, \"CRTC_W\", size_.width);\n-\t\tdrmRequest->addProperty(plane_, \"CRTC_H\", size_.height);\n+\t\tdrmRequest->addProperty(plane_, \"SRC_X\", src_.x << 16);\n+\t\tdrmRequest->addProperty(plane_, \"SRC_Y\", src_.y << 16);\n+\t\tdrmRequest->addProperty(plane_, \"SRC_W\", src_.width << 16);\n+\t\tdrmRequest->addProperty(plane_, \"SRC_H\", src_.height << 16);\n+\t\tdrmRequest->addProperty(plane_, \"CRTC_X\", dst_.x);\n+\t\tdrmRequest->addProperty(plane_, \"CRTC_Y\", dst_.y);\n+\t\tdrmRequest->addProperty(plane_, \"CRTC_W\", dst_.width);\n+\t\tdrmRequest->addProperty(plane_, \"CRTC_H\", dst_.height);\n \n \t\tflags |= DRM::AtomicRequest::FlagAllowModeset;\n \t}\ndiff --git a/src/cam/kms_sink.h b/src/cam/kms_sink.h\nindex 8f5f08667cea..76c4e611bf85 100644\n--- a/src/cam/kms_sink.h\n+++ b/src/cam/kms_sink.h\n@@ -50,6 +50,11 @@ private:\n \n \tint selectPipeline(const libcamera::PixelFormat &format);\n \tint configurePipeline(const libcamera::PixelFormat &format);\n+\tbool testModeSet(DRM::FrameBuffer *drmBuffer,\n+\t\t\t const libcamera::Rectangle &src,\n+\t\t\t const libcamera::Rectangle &dst);\n+\tbool setupComposition(DRM::FrameBuffer *drmBuffer);\n+\n \tvoid requestComplete(DRM::AtomicRequest *request);\n \n \tDRM::Device dev_;\n@@ -63,6 +68,9 @@ private:\n \tlibcamera::Size size_;\n \tunsigned int stride_;\n \n+\tlibcamera::Rectangle src_;\n+\tlibcamera::Rectangle dst_;\n+\n \tstd::map<libcamera::FrameBuffer *, std::unique_ptr<DRM::FrameBuffer>> buffers_;\n \n \tstd::mutex lock_;\n", "prefixes": [ "libcamera-devel", "3/3" ] }