Patch Detail
Show a patch.
GET /api/patches/17030/?format=api
{ "id": 17030, "url": "https://patchwork.libcamera.org/api/patches/17030/?format=api", "web_url": "https://patchwork.libcamera.org/patch/17030/", "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": "<20220808214851.30804-1-laurent.pinchart@ideasonboard.com>", "date": "2022-08-08T21:48:51", "name": "[libcamera-devel,v1.1,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": "537053c7c433b8809f33ee0e09cb667564cc248f", "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/17030/mbox/", "series": [ { "id": 3391, "url": "https://patchwork.libcamera.org/api/series/3391/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3391", "date": "2022-08-08T21:48:51", "name": null, "version": 1, "mbox": "https://patchwork.libcamera.org/series/3391/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/17030/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/17030/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 B6FB0C3272\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 8 Aug 2022 21:49:05 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 0794363327;\n\tMon, 8 Aug 2022 23:49:05 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id BC71463315\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 8 Aug 2022 23:49:02 +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 33735481;\n\tMon, 8 Aug 2022 23:49:02 +0200 (CEST)" ], "DKIM-Signature": [ "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1659995345;\n\tbh=O8NTOBXaio3ZAHaumbxSJA6EAfzLoU3YloAPeokh/XE=;\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=Ul/ybUDDQOCEOV43PMY2+MFTLfL1uBxHIOKGShCR3pAsWGti6IU0GYgmcCrhIdvup\n\t80dxGP5pK/0D+D/Z3uggh4fYYhM1GtcPCtyWbQkUMF83eGMvBGVHWJLkO0vPj2ZmID\n\ts94tYHY5rsQ0x3ejGoa3rp9t5n/6bmN/fIJh5B3uXn1VU3tlx0mrcv47srDKENjLDm\n\tHpB0rILTEWVySD6UINwoXRvH7glOZ4g+Bopp3PFsTc8StMD3km1C7wEpVZOQcYET1r\n\t7x/efFyhNriakraNR+m2LmJEsRsT0E+r5QyGQCyRmzt+miSyoZGRx2E96E0WjjEVu/\n\tAvoKihOMuChVA==", "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1659995342;\n\tbh=O8NTOBXaio3ZAHaumbxSJA6EAfzLoU3YloAPeokh/XE=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=GPcWFqABUHojmR/71r41fA2PCf8BROEzK74tviJTL3O61Dkoio4YDJk6Pe9NQ5eUR\n\tQ4fR+UjUXrlWplpvnvWoPw5gQ1MJVGJDtb4vrZxmaJIUllHIeN1SC6T33jTZihokMs\n\tdz246eh4WOmNmz40PtVLCYxc64l2sdaaAOLYduyk=" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"GPcWFqAB\"; dkim-atps=neutral", "To": "libcamera-devel@lists.libcamera.org", "Date": "Tue, 9 Aug 2022 00:48:51 +0300", "Message-Id": "<20220808214851.30804-1-laurent.pinchart@ideasonboard.com>", "X-Mailer": "git-send-email 2.35.1", "In-Reply-To": "<20220807180100.396-4-laurent.pinchart@ideasonboard.com>", "References": "<20220807180100.396-4-laurent.pinchart@ideasonboard.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH v1.1 3/3] cam: kms_sink: Scale the frame\n\tbuffer to 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 fiyr 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>\nReviewed-by: Eric Curtin <ecurtin@redhat.com>\n---\nChanges since v1:\n\n- Maintain the aspect ratio if possible\n---\n src/cam/kms_sink.cpp | 109 +++++++++++++++++++++++++++++++++++++++----\n src/cam/kms_sink.h | 8 ++++\n 2 files changed, 109 insertions(+), 8 deletions(-)", "diff": "diff --git a/src/cam/kms_sink.cpp b/src/cam/kms_sink.cpp\nindex 16435ede6b6a..17e2fa69bff7 100644\n--- a/src/cam/kms_sink.cpp\n+++ b/src/cam/kms_sink.cpp\n@@ -284,6 +284,94 @@ 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, preserving aspect ratio. */\n+\tlibcamera::Rectangle src = framebuffer;\n+\tlibcamera::Rectangle dst = display.size().boundedToAspectRatio(framebuffer.size())\n+\t\t\t\t\t\t .centeredTo(display.center());\n+\n+\tif (testModeSet(drmBuffer, src, dst)) {\n+\t\tstd::cout << \"KMS: full-screen scaled output, square pixels\"\n+\t\t\t << std::endl;\n+\t\tsrc_ = src;\n+\t\tdst_ = dst;\n+\t\treturn true;\n+\t}\n+\n+\t/*\n+\t * 2. Scale the frame buffer to full screen, without preserving aspect\n+\t * ratio.\n+\t */\n+\tsrc = framebuffer;\n+\tdst = display;\n+\n+\tif (testModeSet(drmBuffer, src, dst)) {\n+\t\tstd::cout << \"KMS: full-screen scaled output, non-square pixels\"\n+\t\t\t << std::endl;\n+\t\tsrc_ = src;\n+\t\tdst_ = dst;\n+\t\treturn true;\n+\t}\n+\n+\t/* 3. 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/* 4. 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 +395,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", "v1.1", "3/3" ] }