[libcamera-devel] [RFC PATCH v1 06/12] libcamera: framebuffer: Add a function to check if planes are contiguous

Kieran Bingham kieran.bingham at ideasonboard.com
Fri Sep 3 10:24:02 CEST 2021


On 02/09/2021 19:07, Laurent Pinchart wrote:
> Hi Kieran,
> 
> On Thu, Sep 02, 2021 at 10:43:56AM +0100, Kieran Bingham wrote:
>> On 02/09/2021 05:22, Laurent Pinchart wrote:
>>> Multi-planar frame buffers can store their planes contiguously in
>>> memory, or split them in discontiguous memory areas. Add a private
>>> function to check in which of these two categories the frame buffer
>>> belongs. This will be used to correctly handle the differences between
>>> the V4L2 single and multi planar APIs.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
>>> ---
>>>  include/libcamera/internal/framebuffer.h |  2 ++
>>>  src/libcamera/framebuffer.cpp            | 45 +++++++++++++++++++++++-
>>>  2 files changed, 46 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/include/libcamera/internal/framebuffer.h b/include/libcamera/internal/framebuffer.h
>>> index 606aed2b4782..cd33c295466e 100644
>>> --- a/include/libcamera/internal/framebuffer.h
>>> +++ b/include/libcamera/internal/framebuffer.h
>>> @@ -21,9 +21,11 @@ public:
>>>  	Private();
>>>  
>>>  	void setRequest(Request *request) { request_ = request; }
>>> +	bool isContiguous() const { return isContiguous_; }
>>>  
>>>  private:
>>>  	Request *request_;
>>> +	bool isContiguous_;
>>>  };
>>>  
>>>  } /* namespace libcamera */
>>> diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp
>>> index 53ef89bf458f..99265b44da43 100644
>>> --- a/src/libcamera/framebuffer.cpp
>>> +++ b/src/libcamera/framebuffer.cpp
>>> @@ -106,7 +106,7 @@ LOG_DEFINE_CATEGORY(Buffer)
>>>   */
>>>  
>>>  FrameBuffer::Private::Private()
>>> -	: request_(nullptr)
>>> +	: request_(nullptr), isContiguous_(true)
>>>  {
>>>  }
>>>  
>>> @@ -120,6 +120,17 @@ FrameBuffer::Private::Private()
>>>   * handlers, it is called by the pipeline handlers themselves.
>>>   */
>>>  
>>> +/**
>>> + * \fn FrameBuffer::Private::isContiguous()
>>> + * \brief Check if the frame buffer stores planes contiguously in memory
>>> + *
>>> + * Multi-planar frame buffers can store their planes contiguously in memory, or
>>> + * split them in discontiguous memory areas. This function checks in which of
>>
>> 'split them into discontiguous'
>>
>>> + * these two categories the frame buffer belongs.
>>> + *
>>> + * \return True if the planes are stored contiguously in memory, false otherwise
>>> + */
>>> +
>>>  /**
>>>   * \class FrameBuffer
>>>   * \brief Frame buffer data and its associated dynamic metadata
>>> @@ -199,9 +210,41 @@ FrameBuffer::FrameBuffer(const std::vector<Plane> &planes, unsigned int cookie)
>>>  	: Extensible(std::make_unique<Private>()), planes_(planes),
>>>  	  cookie_(cookie)
>>>  {
>>> +	unsigned int offset = 0;
>>> +
>>>  	/* \todo Remove the assertions after sufficient testing */
>>>  	for (const auto &plane : planes_)
>>>  		ASSERT(plane.offset != Plane::kInvalidOffset);
>>> +
>>> +	bool isContiguous = true;
>>> +	ino_t inode = 0;
>>> +
>>> +	for (const auto &plane : planes_) {
>>> +		if (plane.offset != offset) {
>>> +			isContiguous = false;
>>> +			break;
>>> +		}
>>> +
>>> +		/*
>>> +		 * Two different dmabuf file descriptors may still refer to the
>>> +		 * same dmabuf instance. Check this using inodes.
>>
>> Going back to the FileDescriptor::inode() extension, if that cached the
>> inode (it can't change) on either first call, or construction, couldn't
>> this whole check be simplified to:
>>
>> 		if (plane.fd.inode() != planes_[0].fd.inode()) {
>> 			isContiguous = false;
>> 			break;
>> 		}
> 
> This would call fstat() every time, while the fd comparison here is
> meant to skip the fstat() calls in case the numerical fd match. We could
> do

Did you miss the part where I said "If we cache the inode in
FileDescriptor"?

My intention was that caching there would mean we can simplify
comparisons here, without incurring repeated fstat calls.


> 		if (plane.fd != planes_[0].fd)
> 
> if we introduced an operator==(), but as explained in a reply to the
> patch that adds inode(), I'd like to handle that later, to avoid
> blocking this series.

Ok, I still don't see the harm in caching the inode within
FileDescriptor(), it can't change once read the first time.

But, it can be deferred:

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


>>> +		 */
>>> +		if (plane.fd.fd() != planes_[0].fd.fd()) {
>>> +			if (!inode)
>>> +				inode = planes_[0].fd.inode();
>>> +			if (plane.fd.inode() != inode) {
>>> +				isContiguous = false;
>>> +				break;
>>> +			}
>>> +		}
>>> +
>>> +		offset += plane.length;
>>> +	}
>>> +
>>> +	LOG(Buffer, Debug)
>>> +		<< "Buffer is " << (isContiguous ? "not " : "") << "contiguous";
>>> +
>>> +	_d()->isContiguous_ = isContiguous;
>>>  }
>>>  
>>>  /**
> 


More information about the libcamera-devel mailing list