[libcamera-devel] [PATCH v3 25/30] cam: drm: Avoid importing the same dmabuf multiple times

Kieran Bingham kieran.bingham at ideasonboard.com
Tue Sep 7 13:49:37 CEST 2021


On 06/09/2021 23:56, Laurent Pinchart wrote:
> 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 <laurent.pinchart at ideasonboard.com>
> Reviewed-by: Jean-Michel Hautbois <jeanmichel.hautbois at ideasonboard.com>

Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

> ---
>  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<FrameBuffer> Device::createFrameBuffer(
>  	int ret;
>  
>  	const std::vector<libcamera::FrameBuffer::Plane> &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<Plane> planes_;
> +	std::map<int, Plane> planes_;
>  };
>  
>  class AtomicRequest
> 


More information about the libcamera-devel mailing list