From patchwork Mon Sep 6 22:56:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13691 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 75252BE175 for ; Mon, 6 Sep 2021 22:57:49 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3401C6917E; Tue, 7 Sep 2021 00:57:49 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="PrNYx+b9"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E9F6A69167 for ; Tue, 7 Sep 2021 00:57:08 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 87204891; Tue, 7 Sep 2021 00:57:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630969028; bh=KGEkV/+jB/Kl24eWKUk1fHAkY97gdEaD0mhGkRoNyns=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PrNYx+b94uUkhwggRNpMu9xf4GB7ZRgpzSdw/V2WQBtI9BLUzR7VYkmG1Z4Uet6AT xNuQ24AmVGnVJ2QdtgWSYaWpiFp8Au0DYkVB7L3Hh8g0vjRW1DVtHBhBB0iOG9K7n5 IEd3H1qVmkTbXlLo5xE+vZxOAaREV+K5DjK2GfWs= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 7 Sep 2021 01:56:31 +0300 Message-Id: <20210906225636.14683-25-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906225420.13275-1-laurent.pinchart@ideasonboard.com> References: <20210906225420.13275-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 25/30] cam: drm: Avoid importing the same dmabuf multiple times X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" When creating a DRM frame buffer, the dmabufs for the planes are imported as GEM objects. For multi-planar formats, all planes may use the same dmabuf, which results in multiple imports. This doesn't cause any issue at import time, as DRM detects this situation and returns the same GEM object. However, when destroying the frame buffer, the same GEM object ends up being closed multiple times, which generates an error. Fix this by avoiding multiple imports of the same dmabuf for the same frame buffer. While the issue may theoretically occur with identical dmabufs for different frame buffers, this is quite unlikely and is thus not addressed. Signed-off-by: Laurent Pinchart Reviewed-by: Jean-Michel Hautbois Reviewed-by: Kieran Bingham --- src/cam/drm.cpp | 29 +++++++++++++++++------------ src/cam/drm.h | 2 +- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/cam/drm.cpp b/src/cam/drm.cpp index d5a75d039fd8..f25300913a7f 100644 --- a/src/cam/drm.cpp +++ b/src/cam/drm.cpp @@ -283,9 +283,9 @@ FrameBuffer::FrameBuffer(Device *dev) FrameBuffer::~FrameBuffer() { - for (FrameBuffer::Plane &plane : planes_) { + for (const auto &plane : planes_) { struct drm_gem_close gem_close = { - .handle = plane.handle, + .handle = plane.second.handle, .pad = 0, }; int ret; @@ -605,22 +605,27 @@ std::unique_ptr Device::createFrameBuffer( int ret; const std::vector &planes = buffer.planes(); - fb->planes_.reserve(planes.size()); unsigned int i = 0; for (const libcamera::FrameBuffer::Plane &plane : planes) { + int fd = plane.fd.fd(); uint32_t handle; - ret = drmPrimeFDToHandle(fd_, plane.fd.fd(), &handle); - if (ret < 0) { - ret = -errno; - std::cerr - << "Unable to import framebuffer dmabuf: " - << strerror(-ret) << std::endl; - return nullptr; - } + auto iter = fb->planes_.find(fd); + if (iter == fb->planes_.end()) { + ret = drmPrimeFDToHandle(fd_, plane.fd.fd(), &handle); + if (ret < 0) { + ret = -errno; + std::cerr + << "Unable to import framebuffer dmabuf: " + << strerror(-ret) << std::endl; + return nullptr; + } - fb->planes_.push_back({ handle }); + fb->planes_[fd] = { handle }; + } else { + handle = iter->second.handle; + } handles[i] = handle; offsets[i] = plane.offset; diff --git a/src/cam/drm.h b/src/cam/drm.h index 00f7e798b771..0b88f9a33912 100644 --- a/src/cam/drm.h +++ b/src/cam/drm.h @@ -242,7 +242,7 @@ private: FrameBuffer(Device *dev); - std::vector planes_; + std::map planes_; }; class AtomicRequest