[libcamera-devel,v5,1/3] libcamera: Move DmaHeap to HeapAllocator as a base class
diff mbox series

Message ID 20230516080459.711347-2-chenghaoyang@google.com
State Superseded
Headers show
Series
  • Add HeapAllocator
Related show

Commit Message

Cheng-Hao Yang May 16, 2023, 8:03 a.m. UTC
From: Cheng-Hao Yang <chenghaoyang@chromium.org>

As other components (like the WIP virtual pipeline handler) also need a
heap allocator, move DmaHeap from raspberry pi pipeline handler to a
general HeapAllocator as a base class.

Signed-off-by: Harvey Yang <chenghaoyang@chromium.org>
---
 .../libcamera/internal/heap_allocator.h       |  18 ++-
 include/libcamera/internal/meson.build        |   1 +
 src/libcamera/heap_allocator.cpp              | 128 ++++++++++++++++++
 src/libcamera/meson.build                     |   1 +
 src/libcamera/pipeline/meson.build            |   5 +-
 src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp  |  90 ------------
 src/libcamera/pipeline/rpi/vc4/meson.build    |   5 +-
 src/libcamera/pipeline/rpi/vc4/vc4.cpp        |  11 +-
 8 files changed, 145 insertions(+), 114 deletions(-)
 rename src/libcamera/pipeline/rpi/vc4/dma_heaps.h => include/libcamera/internal/heap_allocator.h (50%)
 create mode 100644 src/libcamera/heap_allocator.cpp
 delete mode 100644 src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp

Comments

Jacopo Mondi May 16, 2023, 10:24 a.m. UTC | #1
Hi Harvey
On Tue, May 16, 2023 at 08:03:17AM +0000, Harvey Yang via libcamera-devel wrote:
> From: Cheng-Hao Yang <chenghaoyang@chromium.org>
>
> As other components (like the WIP virtual pipeline handler) also need a
> heap allocator, move DmaHeap from raspberry pi pipeline handler to a
> general HeapAllocator as a base class.
>
> Signed-off-by: Harvey Yang <chenghaoyang@chromium.org>
> ---
>  .../libcamera/internal/heap_allocator.h       |  18 ++-
>  include/libcamera/internal/meson.build        |   1 +
>  src/libcamera/heap_allocator.cpp              | 128 ++++++++++++++++++
>  src/libcamera/meson.build                     |   1 +
>  src/libcamera/pipeline/meson.build            |   5 +-
>  src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp  |  90 ------------
>  src/libcamera/pipeline/rpi/vc4/meson.build    |   5 +-
>  src/libcamera/pipeline/rpi/vc4/vc4.cpp        |  11 +-
>  8 files changed, 145 insertions(+), 114 deletions(-)
>  rename src/libcamera/pipeline/rpi/vc4/dma_heaps.h => include/libcamera/internal/heap_allocator.h (50%)
>  create mode 100644 src/libcamera/heap_allocator.cpp
>  delete mode 100644 src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
>
> diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h b/include/libcamera/internal/heap_allocator.h
> similarity index 50%
> rename from src/libcamera/pipeline/rpi/vc4/dma_heaps.h
> rename to include/libcamera/internal/heap_allocator.h
> index 0a4a8d86..d061fdce 100644
> --- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h
> +++ b/include/libcamera/internal/heap_allocator.h
> @@ -1,8 +1,8 @@
>  /* SPDX-License-Identifier: LGPL-2.1-or-later */
>  /*
> - * Copyright (C) 2020, Raspberry Pi Ltd
> + * Copyright (C) 2023, Google Inc.

Why can't you keep both ? If the code comes from RPi they copyright
should be retained.

>   *
> - * dma_heaps.h - Helper class for dma-heap allocations.
> + * heap_allocator.h - Helper class for heap buffer allocations.
>   */
>
>  #pragma once
> @@ -13,20 +13,18 @@
>
>  namespace libcamera {
>
> -namespace RPi {
> +class Heap;
>
> -class DmaHeap
> +class HeapAllocator
>  {
>  public:
> -	DmaHeap();
> -	~DmaHeap();
> -	bool isValid() const { return dmaHeapHandle_.isValid(); }
> +	HeapAllocator();
> +	~HeapAllocator();
> +	bool isValid() const;
>  	UniqueFD alloc(const char *name, std::size_t size);
>
>  private:
> -	UniqueFD dmaHeapHandle_;
> +	std::unique_ptr<Heap> heap_;
>  };
>
> -} /* namespace RPi */
> -
>  } /* namespace libcamera */
> diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
> index d7508805..9d25c289 100644
> --- a/include/libcamera/internal/meson.build
> +++ b/include/libcamera/internal/meson.build
> @@ -26,6 +26,7 @@ libcamera_internal_headers = files([
>      'device_enumerator_udev.h',
>      'formats.h',
>      'framebuffer.h',
> +    'heap_allocator.h',
>      'ipa_manager.h',
>      'ipa_module.h',
>      'ipa_proxy.h',
> diff --git a/src/libcamera/heap_allocator.cpp b/src/libcamera/heap_allocator.cpp
> new file mode 100644
> index 00000000..e9476de5
> --- /dev/null
> +++ b/src/libcamera/heap_allocator.cpp
> @@ -0,0 +1,128 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2020, Raspberry Pi Ltd
> + *
> + * heap_allocator.cpp - Helper class for heap buffer allocations.
> + */
> +
> +#include "libcamera/internal/heap_allocator.h"
> +
> +#include <array>
> +#include <fcntl.h>
> +#include <sys/ioctl.h>
> +#include <unistd.h>
> +
> +#include <linux/dma-buf.h>
> +#include <linux/dma-heap.h>
> +
> +#include <libcamera/base/log.h>
> +
> +namespace libcamera {
> +
> +/*
> + * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma
> + * to only have to worry about importing.
> + *
> + * Annoyingly, should the cma heap size be specified on the kernel command line
> + * instead of DT, the heap gets named "reserved" instead.
> + */
> +static constexpr std::array<const char *, 2> dmaHeapNames = {
> +	"/dev/dma_heap/linux,cma",
> +	"/dev/dma_heap/reserved"
> +};
> +
> +LOG_DEFINE_CATEGORY(HeapAllocator)
> +
> +class Heap
> +{
> +public:
> +	virtual ~Heap() = default;
> +	bool isValid() const { return handle_.isValid(); }
> +	virtual UniqueFD alloc(const char *name, std::size_t size) = 0;
> +
> +protected:
> +	UniqueFD handle_;
> +};
> +
> +class DmaHeap : public Heap
> +{
> +public:
> +	DmaHeap();
> +	~DmaHeap();
> +	UniqueFD alloc(const char *name, std::size_t size) override;
> +};
> +
> +DmaHeap::DmaHeap()
> +{
> +	for (const char *name : dmaHeapNames) {
> +		int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
> +		if (ret < 0) {
> +			ret = errno;
> +			LOG(HeapAllocator, Debug) << "DmaHeap failed to open " << name << ": "
> +						  << strerror(ret);
> +			continue;
> +		}
> +
> +		handle_ = UniqueFD(ret);
> +		break;
> +	}
> +
> +	if (!handle_.isValid())
> +		LOG(HeapAllocator, Error) << "DmaHeap could not open any dmaHeap device";
> +}
> +
> +DmaHeap::~DmaHeap() = default;
> +
> +UniqueFD DmaHeap::alloc(const char *name, std::size_t size)
> +{
> +	int ret;
> +
> +	if (!name)
> +		return {};
> +
> +	struct dma_heap_allocation_data alloc = {};
> +
> +	alloc.len = size;
> +	alloc.fd_flags = O_CLOEXEC | O_RDWR;
> +
> +	ret = ::ioctl(handle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc);
> +	if (ret < 0) {
> +		LOG(HeapAllocator, Error) << "DmaHeap allocation failure for "
> +					  << name;
> +		return {};
> +	}
> +
> +	UniqueFD allocFd(alloc.fd);
> +	ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name);
> +	if (ret < 0) {
> +		LOG(HeapAllocator, Error) << "DmaHeap naming failure for "
> +					  << name;
> +		return {};
> +	}
> +
> +	return allocFd;
> +}
> +
> +HeapAllocator::HeapAllocator()
> +{
> +	heap_ = std::make_unique<DmaHeap>();
> +}
> +
> +HeapAllocator::~HeapAllocator() = default;
> +
> +bool HeapAllocator::isValid() const
> +{
> +	return heap_->isValid();
> +}
> +
> +UniqueFD HeapAllocator::alloc(const char *name, std::size_t size)
> +{
> +	if (!isValid()) {
> +		LOG(HeapAllocator, Fatal) << "Allocation attempted without allocator" << name;
> +		return {};
> +	}
> +
> +	return heap_->alloc(name, size);
> +}
> +
> +} /* namespace libcamera */
> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
> index d4385041..aa2d32a0 100644
> --- a/src/libcamera/meson.build
> +++ b/src/libcamera/meson.build
> @@ -22,6 +22,7 @@ libcamera_sources = files([
>      'framebuffer.cpp',
>      'framebuffer_allocator.cpp',
>      'geometry.cpp',
> +    'heap_allocator.cpp',
>      'ipa_controls.cpp',
>      'ipa_data_serializer.cpp',
>      'ipa_interface.cpp',
> diff --git a/src/libcamera/pipeline/meson.build b/src/libcamera/pipeline/meson.build
> index 8a61991c..b6160d34 100644
> --- a/src/libcamera/pipeline/meson.build
> +++ b/src/libcamera/pipeline/meson.build
> @@ -12,9 +12,6 @@ foreach pipeline : pipelines
>          continue
>      endif
>
> -    subdirs += pipeline
>      subdir(pipeline)
> -
> -    # Don't reuse the pipeline variable below, the subdirectory may have
> -    # overwritten it.
> +    subdirs += pipeline

The comment you removed says exactly not to do this :)

Why do you need this change ?


>  endforeach
> diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp b/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
> deleted file mode 100644
> index 317b1fc1..00000000
> --- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
> +++ /dev/null
> @@ -1,90 +0,0 @@
> -/* SPDX-License-Identifier: LGPL-2.1-or-later */
> -/*
> - * Copyright (C) 2020, Raspberry Pi Ltd
> - *
> - * dma_heaps.h - Helper class for dma-heap allocations.
> - */
> -
> -#include "dma_heaps.h"
> -
> -#include <array>
> -#include <fcntl.h>
> -#include <linux/dma-buf.h>
> -#include <linux/dma-heap.h>
> -#include <sys/ioctl.h>
> -#include <unistd.h>
> -
> -#include <libcamera/base/log.h>
> -
> -/*
> - * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma
> - * to only have to worry about importing.
> - *
> - * Annoyingly, should the cma heap size be specified on the kernel command line
> - * instead of DT, the heap gets named "reserved" instead.
> - */
> -static constexpr std::array<const char *, 2> heapNames = {
> -	"/dev/dma_heap/linux,cma",
> -	"/dev/dma_heap/reserved"
> -};
> -
> -namespace libcamera {
> -
> -LOG_DECLARE_CATEGORY(RPI)
> -
> -namespace RPi {
> -
> -DmaHeap::DmaHeap()
> -{
> -	for (const char *name : heapNames) {
> -		int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
> -		if (ret < 0) {
> -			ret = errno;
> -			LOG(RPI, Debug) << "Failed to open " << name << ": "
> -					<< strerror(ret);
> -			continue;
> -		}
> -
> -		dmaHeapHandle_ = UniqueFD(ret);
> -		break;
> -	}
> -
> -	if (!dmaHeapHandle_.isValid())
> -		LOG(RPI, Error) << "Could not open any dmaHeap device";
> -}
> -
> -DmaHeap::~DmaHeap() = default;
> -
> -UniqueFD DmaHeap::alloc(const char *name, std::size_t size)
> -{
> -	int ret;
> -
> -	if (!name)
> -		return {};
> -
> -	struct dma_heap_allocation_data alloc = {};
> -
> -	alloc.len = size;
> -	alloc.fd_flags = O_CLOEXEC | O_RDWR;
> -
> -	ret = ::ioctl(dmaHeapHandle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc);
> -	if (ret < 0) {
> -		LOG(RPI, Error) << "dmaHeap allocation failure for "
> -				<< name;
> -		return {};
> -	}
> -
> -	UniqueFD allocFd(alloc.fd);
> -	ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name);
> -	if (ret < 0) {
> -		LOG(RPI, Error) << "dmaHeap naming failure for "
> -				<< name;
> -		return {};
> -	}
> -
> -	return allocFd;
> -}
> -
> -} /* namespace RPi */
> -
> -} /* namespace libcamera */
> diff --git a/src/libcamera/pipeline/rpi/vc4/meson.build b/src/libcamera/pipeline/rpi/vc4/meson.build
> index cdb049c5..b2b79735 100644
> --- a/src/libcamera/pipeline/rpi/vc4/meson.build
> +++ b/src/libcamera/pipeline/rpi/vc4/meson.build
> @@ -1,8 +1,5 @@
>  # SPDX-License-Identifier: CC0-1.0
>
> -libcamera_sources += files([
> -    'dma_heaps.cpp',
> -    'vc4.cpp',
> -])
> +libcamera_sources += files(['vc4.cpp'])
>
>  subdir('data')
> diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> index 018cf488..410ecfaf 100644
> --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> @@ -12,12 +12,11 @@
>  #include <libcamera/formats.h>
>
>  #include "libcamera/internal/device_enumerator.h"
> +#include "libcamera/internal/heap_allocator.h"
>
>  #include "../common/pipeline_base.h"
>  #include "../common/rpi_stream.h"
>
> -#include "dma_heaps.h"
> -
>  using namespace std::chrono_literals;
>
>  namespace libcamera {
> @@ -87,7 +86,7 @@ public:
>  	RPi::Device<Isp, 4> isp_;
>
>  	/* DMAHEAP allocation helper. */
> -	RPi::DmaHeap dmaHeap_;
> +	HeapAllocator heapAllocator_;
>  	SharedFD lsTable_;
>
>  	struct Config {
> @@ -296,7 +295,7 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer
>  {
>  	Vc4CameraData *data = static_cast<Vc4CameraData *>(cameraData.get());
>
> -	if (!data->dmaHeap_.isValid())
> +	if (!data->heapAllocator_.isValid())
>  		return -ENOMEM;
>
>  	MediaEntity *unicamImage = unicam->getEntityByName("unicam-image");
> @@ -670,9 +669,9 @@ int Vc4CameraData::platformConfigureIpa(ipa::RPi::ConfigParams &params)
>  {
>  	params.ispControls = isp_[Isp::Input].dev()->controls();
>
> -	/* Allocate the lens shading table via dmaHeap and pass to the IPA. */
> +	/* Allocate the lens shading table via heapAllocator and pass to the IPA. */
>  	if (!lsTable_.isValid()) {
> -		lsTable_ = SharedFD(dmaHeap_.alloc("ls_grid", ipa::RPi::MaxLsGridSize));
> +		lsTable_ = SharedFD(heapAllocator_.alloc("ls_grid", ipa::RPi::MaxLsGridSize));
>  		if (!lsTable_.isValid())
>  			return -ENOMEM;
>
> --
> 2.40.1.606.ga4b1b128d6-goog
>
Kieran Bingham May 16, 2023, 11:27 a.m. UTC | #2
Quoting Jacopo Mondi via libcamera-devel (2023-05-16 11:24:33)
> Hi Harvey
> On Tue, May 16, 2023 at 08:03:17AM +0000, Harvey Yang via libcamera-devel wrote:
> > From: Cheng-Hao Yang <chenghaoyang@chromium.org>
> >
> > As other components (like the WIP virtual pipeline handler) also need a
> > heap allocator, move DmaHeap from raspberry pi pipeline handler to a
> > general HeapAllocator as a base class.
> >
> > Signed-off-by: Harvey Yang <chenghaoyang@chromium.org>
> > ---
> >  .../libcamera/internal/heap_allocator.h       |  18 ++-
> >  include/libcamera/internal/meson.build        |   1 +
> >  src/libcamera/heap_allocator.cpp              | 128 ++++++++++++++++++
> >  src/libcamera/meson.build                     |   1 +
> >  src/libcamera/pipeline/meson.build            |   5 +-
> >  src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp  |  90 ------------
> >  src/libcamera/pipeline/rpi/vc4/meson.build    |   5 +-
> >  src/libcamera/pipeline/rpi/vc4/vc4.cpp        |  11 +-
> >  8 files changed, 145 insertions(+), 114 deletions(-)
> >  rename src/libcamera/pipeline/rpi/vc4/dma_heaps.h => include/libcamera/internal/heap_allocator.h (50%)
> >  create mode 100644 src/libcamera/heap_allocator.cpp
> >  delete mode 100644 src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
> >
> > diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h b/include/libcamera/internal/heap_allocator.h
> > similarity index 50%
> > rename from src/libcamera/pipeline/rpi/vc4/dma_heaps.h
> > rename to include/libcamera/internal/heap_allocator.h
> > index 0a4a8d86..d061fdce 100644
> > --- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h
> > +++ b/include/libcamera/internal/heap_allocator.h
> > @@ -1,8 +1,8 @@
> >  /* SPDX-License-Identifier: LGPL-2.1-or-later */
> >  /*
> > - * Copyright (C) 2020, Raspberry Pi Ltd
> > + * Copyright (C) 2023, Google Inc.
> 
> Why can't you keep both ? If the code comes from RPi they copyright
> should be retained.

I'm sure we've been here before ;-)

Indeed, please don't drop copyrights when moving code around.


> 
> >   *
> > - * dma_heaps.h - Helper class for dma-heap allocations.
> > + * heap_allocator.h - Helper class for heap buffer allocations.
> >   */
> >
> >  #pragma once
> > @@ -13,20 +13,18 @@
> >
> >  namespace libcamera {
> >
> > -namespace RPi {
> > +class Heap;
> >
> > -class DmaHeap
> > +class HeapAllocator
> >  {
> >  public:
> > -     DmaHeap();
> > -     ~DmaHeap();
> > -     bool isValid() const { return dmaHeapHandle_.isValid(); }
> > +     HeapAllocator();
> > +     ~HeapAllocator();
> > +     bool isValid() const;
> >       UniqueFD alloc(const char *name, std::size_t size);
> >
> >  private:
> > -     UniqueFD dmaHeapHandle_;
> > +     std::unique_ptr<Heap> heap_;
> >  };
> >
> > -} /* namespace RPi */
> > -
> >  } /* namespace libcamera */
> > diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
> > index d7508805..9d25c289 100644
> > --- a/include/libcamera/internal/meson.build
> > +++ b/include/libcamera/internal/meson.build
> > @@ -26,6 +26,7 @@ libcamera_internal_headers = files([
> >      'device_enumerator_udev.h',
> >      'formats.h',
> >      'framebuffer.h',
> > +    'heap_allocator.h',
> >      'ipa_manager.h',
> >      'ipa_module.h',
> >      'ipa_proxy.h',
> > diff --git a/src/libcamera/heap_allocator.cpp b/src/libcamera/heap_allocator.cpp
> > new file mode 100644
> > index 00000000..e9476de5
> > --- /dev/null
> > +++ b/src/libcamera/heap_allocator.cpp
> > @@ -0,0 +1,128 @@
> > +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> > +/*
> > + * Copyright (C) 2020, Raspberry Pi Ltd
> > + *
> > + * heap_allocator.cpp - Helper class for heap buffer allocations.
> > + */
> > +
> > +#include "libcamera/internal/heap_allocator.h"
> > +
> > +#include <array>
> > +#include <fcntl.h>
> > +#include <sys/ioctl.h>
> > +#include <unistd.h>
> > +
> > +#include <linux/dma-buf.h>
> > +#include <linux/dma-heap.h>
> > +
> > +#include <libcamera/base/log.h>
> > +
> > +namespace libcamera {
> > +
> > +/*
> > + * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma
> > + * to only have to worry about importing.
> > + *
> > + * Annoyingly, should the cma heap size be specified on the kernel command line
> > + * instead of DT, the heap gets named "reserved" instead.
> > + */
> > +static constexpr std::array<const char *, 2> dmaHeapNames = {
> > +     "/dev/dma_heap/linux,cma",
> > +     "/dev/dma_heap/reserved"

On my x86 pc, I have "/dev/dma_heap/system" too. I don't know if we
shoudl add that ... but maybe something to explore later.

This is fine to keep as it is though here I think.

> > +};
> > +
> > +LOG_DEFINE_CATEGORY(HeapAllocator)
> > +
> > +class Heap
> > +{
> > +public:
> > +     virtual ~Heap() = default;
> > +     bool isValid() const { return handle_.isValid(); }
> > +     virtual UniqueFD alloc(const char *name, std::size_t size) = 0;
> > +
> > +protected:
> > +     UniqueFD handle_;
> > +};
> > +
> > +class DmaHeap : public Heap
> > +{
> > +public:
> > +     DmaHeap();
> > +     ~DmaHeap();
> > +     UniqueFD alloc(const char *name, std::size_t size) override;
> > +};
> > +
> > +DmaHeap::DmaHeap()
> > +{
> > +     for (const char *name : dmaHeapNames) {
> > +             int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
> > +             if (ret < 0) {
> > +                     ret = errno;
> > +                     LOG(HeapAllocator, Debug) << "DmaHeap failed to open " << name << ": "
> > +                                               << strerror(ret);
> > +                     continue;
> > +             }
> > +
> > +             handle_ = UniqueFD(ret);
> > +             break;
> > +     }
> > +
> > +     if (!handle_.isValid())
> > +             LOG(HeapAllocator, Error) << "DmaHeap could not open any dmaHeap device";
> > +}
> > +
> > +DmaHeap::~DmaHeap() = default;
> > +
> > +UniqueFD DmaHeap::alloc(const char *name, std::size_t size)
> > +{
> > +     int ret;
> > +
> > +     if (!name)
> > +             return {};
> > +
> > +     struct dma_heap_allocation_data alloc = {};
> > +
> > +     alloc.len = size;
> > +     alloc.fd_flags = O_CLOEXEC | O_RDWR;
> > +
> > +     ret = ::ioctl(handle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc);
> > +     if (ret < 0) {
> > +             LOG(HeapAllocator, Error) << "DmaHeap allocation failure for "
> > +                                       << name;
> > +             return {};
> > +     }
> > +
> > +     UniqueFD allocFd(alloc.fd);
> > +     ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name);
> > +     if (ret < 0) {
> > +             LOG(HeapAllocator, Error) << "DmaHeap naming failure for "
> > +                                       << name;
> > +             return {};
> > +     }
> > +
> > +     return allocFd;
> > +}
> > +
> > +HeapAllocator::HeapAllocator()
> > +{
> > +     heap_ = std::make_unique<DmaHeap>();
> > +}
> > +
> > +HeapAllocator::~HeapAllocator() = default;
> > +
> > +bool HeapAllocator::isValid() const
> > +{
> > +     return heap_->isValid();
> > +}
> > +
> > +UniqueFD HeapAllocator::alloc(const char *name, std::size_t size)
> > +{
> > +     if (!isValid()) {
> > +             LOG(HeapAllocator, Fatal) << "Allocation attempted without allocator" << name;
> > +             return {};
> > +     }
> > +
> > +     return heap_->alloc(name, size);
> > +}
> > +
> > +} /* namespace libcamera */
> > diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
> > index d4385041..aa2d32a0 100644
> > --- a/src/libcamera/meson.build
> > +++ b/src/libcamera/meson.build
> > @@ -22,6 +22,7 @@ libcamera_sources = files([
> >      'framebuffer.cpp',
> >      'framebuffer_allocator.cpp',
> >      'geometry.cpp',
> > +    'heap_allocator.cpp',
> >      'ipa_controls.cpp',
> >      'ipa_data_serializer.cpp',
> >      'ipa_interface.cpp',
> > diff --git a/src/libcamera/pipeline/meson.build b/src/libcamera/pipeline/meson.build
> > index 8a61991c..b6160d34 100644
> > --- a/src/libcamera/pipeline/meson.build
> > +++ b/src/libcamera/pipeline/meson.build
> > @@ -12,9 +12,6 @@ foreach pipeline : pipelines
> >          continue
> >      endif
> >
> > -    subdirs += pipeline
> >      subdir(pipeline)
> > -
> > -    # Don't reuse the pipeline variable below, the subdirectory may have
> > -    # overwritten it.
> > +    subdirs += pipeline
> 
> The comment you removed says exactly not to do this :)
> 
> Why do you need this change ?

I presume this is just a bad merge conflict ?

> 
> 
> >  endforeach
> > diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp b/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
> > deleted file mode 100644
> > index 317b1fc1..00000000
> > --- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
> > +++ /dev/null
> > @@ -1,90 +0,0 @@
> > -/* SPDX-License-Identifier: LGPL-2.1-or-later */
> > -/*
> > - * Copyright (C) 2020, Raspberry Pi Ltd
> > - *
> > - * dma_heaps.h - Helper class for dma-heap allocations.
> > - */
> > -
> > -#include "dma_heaps.h"
> > -
> > -#include <array>
> > -#include <fcntl.h>
> > -#include <linux/dma-buf.h>
> > -#include <linux/dma-heap.h>
> > -#include <sys/ioctl.h>
> > -#include <unistd.h>
> > -
> > -#include <libcamera/base/log.h>
> > -
> > -/*
> > - * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma
> > - * to only have to worry about importing.
> > - *
> > - * Annoyingly, should the cma heap size be specified on the kernel command line
> > - * instead of DT, the heap gets named "reserved" instead.
> > - */
> > -static constexpr std::array<const char *, 2> heapNames = {
> > -     "/dev/dma_heap/linux,cma",
> > -     "/dev/dma_heap/reserved"
> > -};
> > -
> > -namespace libcamera {
> > -
> > -LOG_DECLARE_CATEGORY(RPI)
> > -
> > -namespace RPi {
> > -
> > -DmaHeap::DmaHeap()
> > -{
> > -     for (const char *name : heapNames) {
> > -             int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
> > -             if (ret < 0) {
> > -                     ret = errno;
> > -                     LOG(RPI, Debug) << "Failed to open " << name << ": "
> > -                                     << strerror(ret);
> > -                     continue;
> > -             }
> > -
> > -             dmaHeapHandle_ = UniqueFD(ret);
> > -             break;
> > -     }
> > -
> > -     if (!dmaHeapHandle_.isValid())
> > -             LOG(RPI, Error) << "Could not open any dmaHeap device";
> > -}
> > -
> > -DmaHeap::~DmaHeap() = default;
> > -
> > -UniqueFD DmaHeap::alloc(const char *name, std::size_t size)
> > -{
> > -     int ret;
> > -
> > -     if (!name)
> > -             return {};
> > -
> > -     struct dma_heap_allocation_data alloc = {};
> > -
> > -     alloc.len = size;
> > -     alloc.fd_flags = O_CLOEXEC | O_RDWR;
> > -
> > -     ret = ::ioctl(dmaHeapHandle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc);
> > -     if (ret < 0) {
> > -             LOG(RPI, Error) << "dmaHeap allocation failure for "
> > -                             << name;
> > -             return {};
> > -     }
> > -
> > -     UniqueFD allocFd(alloc.fd);
> > -     ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name);
> > -     if (ret < 0) {
> > -             LOG(RPI, Error) << "dmaHeap naming failure for "
> > -                             << name;
> > -             return {};
> > -     }
> > -
> > -     return allocFd;
> > -}
> > -
> > -} /* namespace RPi */
> > -
> > -} /* namespace libcamera */
> > diff --git a/src/libcamera/pipeline/rpi/vc4/meson.build b/src/libcamera/pipeline/rpi/vc4/meson.build
> > index cdb049c5..b2b79735 100644
> > --- a/src/libcamera/pipeline/rpi/vc4/meson.build
> > +++ b/src/libcamera/pipeline/rpi/vc4/meson.build
> > @@ -1,8 +1,5 @@
> >  # SPDX-License-Identifier: CC0-1.0
> >
> > -libcamera_sources += files([
> > -    'dma_heaps.cpp',
> > -    'vc4.cpp',
> > -])
> > +libcamera_sources += files(['vc4.cpp'])
> >
> >  subdir('data')
> > diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > index 018cf488..410ecfaf 100644
> > --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > @@ -12,12 +12,11 @@
> >  #include <libcamera/formats.h>
> >
> >  #include "libcamera/internal/device_enumerator.h"
> > +#include "libcamera/internal/heap_allocator.h"
> >
> >  #include "../common/pipeline_base.h"
> >  #include "../common/rpi_stream.h"
> >
> > -#include "dma_heaps.h"
> > -
> >  using namespace std::chrono_literals;
> >
> >  namespace libcamera {
> > @@ -87,7 +86,7 @@ public:
> >       RPi::Device<Isp, 4> isp_;
> >
> >       /* DMAHEAP allocation helper. */
> > -     RPi::DmaHeap dmaHeap_;
> > +     HeapAllocator heapAllocator_;
> >       SharedFD lsTable_;
> >
> >       struct Config {
> > @@ -296,7 +295,7 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer
> >  {
> >       Vc4CameraData *data = static_cast<Vc4CameraData *>(cameraData.get());
> >
> > -     if (!data->dmaHeap_.isValid())
> > +     if (!data->heapAllocator_.isValid())
> >               return -ENOMEM;
> >
> >       MediaEntity *unicamImage = unicam->getEntityByName("unicam-image");
> > @@ -670,9 +669,9 @@ int Vc4CameraData::platformConfigureIpa(ipa::RPi::ConfigParams &params)
> >  {
> >       params.ispControls = isp_[Isp::Input].dev()->controls();
> >
> > -     /* Allocate the lens shading table via dmaHeap and pass to the IPA. */
> > +     /* Allocate the lens shading table via heapAllocator and pass to the IPA. */
> >       if (!lsTable_.isValid()) {
> > -             lsTable_ = SharedFD(dmaHeap_.alloc("ls_grid", ipa::RPi::MaxLsGridSize));
> > +             lsTable_ = SharedFD(heapAllocator_.alloc("ls_grid", ipa::RPi::MaxLsGridSize));
> >               if (!lsTable_.isValid())
> >                       return -ENOMEM;
> >
> > --
> > 2.40.1.606.ga4b1b128d6-goog
> >
Cheng-Hao Yang May 22, 2023, 8:37 a.m. UTC | #3
Thanks Kieran and Jacopo for another round of review!

On Tue, May 16, 2023 at 7:27 PM Kieran Bingham <
kieran.bingham@ideasonboard.com> wrote:

> Quoting Jacopo Mondi via libcamera-devel (2023-05-16 11:24:33)
> > Hi Harvey
> > On Tue, May 16, 2023 at 08:03:17AM +0000, Harvey Yang via
> libcamera-devel wrote:
> > > From: Cheng-Hao Yang <chenghaoyang@chromium.org>
> > >
> > > As other components (like the WIP virtual pipeline handler) also need a
> > > heap allocator, move DmaHeap from raspberry pi pipeline handler to a
> > > general HeapAllocator as a base class.
> > >
> > > Signed-off-by: Harvey Yang <chenghaoyang@chromium.org>
> > > ---
> > >  .../libcamera/internal/heap_allocator.h       |  18 ++-
> > >  include/libcamera/internal/meson.build        |   1 +
> > >  src/libcamera/heap_allocator.cpp              | 128 ++++++++++++++++++
> > >  src/libcamera/meson.build                     |   1 +
> > >  src/libcamera/pipeline/meson.build            |   5 +-
> > >  src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp  |  90 ------------
> > >  src/libcamera/pipeline/rpi/vc4/meson.build    |   5 +-
> > >  src/libcamera/pipeline/rpi/vc4/vc4.cpp        |  11 +-
> > >  8 files changed, 145 insertions(+), 114 deletions(-)
> > >  rename src/libcamera/pipeline/rpi/vc4/dma_heaps.h =>
> include/libcamera/internal/heap_allocator.h (50%)
> > >  create mode 100644 src/libcamera/heap_allocator.cpp
> > >  delete mode 100644 src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
> > >
> > > diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h
> b/include/libcamera/internal/heap_allocator.h
> > > similarity index 50%
> > > rename from src/libcamera/pipeline/rpi/vc4/dma_heaps.h
> > > rename to include/libcamera/internal/heap_allocator.h
> > > index 0a4a8d86..d061fdce 100644
> > > --- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h
> > > +++ b/include/libcamera/internal/heap_allocator.h
> > > @@ -1,8 +1,8 @@
> > >  /* SPDX-License-Identifier: LGPL-2.1-or-later */
> > >  /*
> > > - * Copyright (C) 2020, Raspberry Pi Ltd
> > > + * Copyright (C) 2023, Google Inc.
> >
> > Why can't you keep both ? If the code comes from RPi they copyright
> > should be retained.
>
I'm sure we've been here before ;-)
>
> Indeed, please don't drop copyrights when moving code around.
>
>

I see. I thought keeping RPi copyright in heap_allocator.cpp is enough, as
that's where DmaHeap stays in this patch. The git mv is just auto generated
as they look pretty much the same.

I'll keep both copyrights in heap_allocator.h & heap_allocator.cpp, as the
APIs
of HeapAllocator are basically the same as those of DeaHeap.


>
> >
> > >   *
> > > - * dma_heaps.h - Helper class for dma-heap allocations.
> > > + * heap_allocator.h - Helper class for heap buffer allocations.
> > >   */
> > >
> > >  #pragma once
> > > @@ -13,20 +13,18 @@
> > >
> > >  namespace libcamera {
> > >
> > > -namespace RPi {
> > > +class Heap;
> > >
> > > -class DmaHeap
> > > +class HeapAllocator
> > >  {
> > >  public:
> > > -     DmaHeap();
> > > -     ~DmaHeap();
> > > -     bool isValid() const { return dmaHeapHandle_.isValid(); }
> > > +     HeapAllocator();
> > > +     ~HeapAllocator();
> > > +     bool isValid() const;
> > >       UniqueFD alloc(const char *name, std::size_t size);
> > >
> > >  private:
> > > -     UniqueFD dmaHeapHandle_;
> > > +     std::unique_ptr<Heap> heap_;
> > >  };
> > >
> > > -} /* namespace RPi */
> > > -
> > >  } /* namespace libcamera */
> > > diff --git a/include/libcamera/internal/meson.build
> b/include/libcamera/internal/meson.build
> > > index d7508805..9d25c289 100644
> > > --- a/include/libcamera/internal/meson.build
> > > +++ b/include/libcamera/internal/meson.build
> > > @@ -26,6 +26,7 @@ libcamera_internal_headers = files([
> > >      'device_enumerator_udev.h',
> > >      'formats.h',
> > >      'framebuffer.h',
> > > +    'heap_allocator.h',
> > >      'ipa_manager.h',
> > >      'ipa_module.h',
> > >      'ipa_proxy.h',
> > > diff --git a/src/libcamera/heap_allocator.cpp
> b/src/libcamera/heap_allocator.cpp
> > > new file mode 100644
> > > index 00000000..e9476de5
> > > --- /dev/null
> > > +++ b/src/libcamera/heap_allocator.cpp
> > > @@ -0,0 +1,128 @@
> > > +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> > > +/*
> > > + * Copyright (C) 2020, Raspberry Pi Ltd
> > > + *
> > > + * heap_allocator.cpp - Helper class for heap buffer allocations.
> > > + */
> > > +
> > > +#include "libcamera/internal/heap_allocator.h"
> > > +
> > > +#include <array>
> > > +#include <fcntl.h>
> > > +#include <sys/ioctl.h>
> > > +#include <unistd.h>
> > > +
> > > +#include <linux/dma-buf.h>
> > > +#include <linux/dma-heap.h>
> > > +
> > > +#include <libcamera/base/log.h>
> > > +
> > > +namespace libcamera {
> > > +
> > > +/*
> > > + * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows
> dmaheap-cma
> > > + * to only have to worry about importing.
> > > + *
> > > + * Annoyingly, should the cma heap size be specified on the kernel
> command line
> > > + * instead of DT, the heap gets named "reserved" instead.
> > > + */
> > > +static constexpr std::array<const char *, 2> dmaHeapNames = {
> > > +     "/dev/dma_heap/linux,cma",
> > > +     "/dev/dma_heap/reserved"
>
> On my x86 pc, I have "/dev/dma_heap/system" too. I don't know if we
> shoudl add that ... but maybe something to explore later.
>
> This is fine to keep as it is though here I think.
>
>
Actually the mediatek device (the new board) uses "/dev/dma_heap/system" as
well. Let's add it now :)


> > > +};
> > > +
> > > +LOG_DEFINE_CATEGORY(HeapAllocator)
> > > +
> > > +class Heap
> > > +{
> > > +public:
> > > +     virtual ~Heap() = default;
> > > +     bool isValid() const { return handle_.isValid(); }
> > > +     virtual UniqueFD alloc(const char *name, std::size_t size) = 0;
> > > +
> > > +protected:
> > > +     UniqueFD handle_;
> > > +};
> > > +
> > > +class DmaHeap : public Heap
> > > +{
> > > +public:
> > > +     DmaHeap();
> > > +     ~DmaHeap();
> > > +     UniqueFD alloc(const char *name, std::size_t size) override;
> > > +};
> > > +
> > > +DmaHeap::DmaHeap()
> > > +{
> > > +     for (const char *name : dmaHeapNames) {
> > > +             int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
> > > +             if (ret < 0) {
> > > +                     ret = errno;
> > > +                     LOG(HeapAllocator, Debug) << "DmaHeap failed to
> open " << name << ": "
> > > +                                               << strerror(ret);
> > > +                     continue;
> > > +             }
> > > +
> > > +             handle_ = UniqueFD(ret);
> > > +             break;
> > > +     }
> > > +
> > > +     if (!handle_.isValid())
> > > +             LOG(HeapAllocator, Error) << "DmaHeap could not open any
> dmaHeap device";
> > > +}
> > > +
> > > +DmaHeap::~DmaHeap() = default;
> > > +
> > > +UniqueFD DmaHeap::alloc(const char *name, std::size_t size)
> > > +{
> > > +     int ret;
> > > +
> > > +     if (!name)
> > > +             return {};
> > > +
> > > +     struct dma_heap_allocation_data alloc = {};
> > > +
> > > +     alloc.len = size;
> > > +     alloc.fd_flags = O_CLOEXEC | O_RDWR;
> > > +
> > > +     ret = ::ioctl(handle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc);
> > > +     if (ret < 0) {
> > > +             LOG(HeapAllocator, Error) << "DmaHeap allocation failure
> for "
> > > +                                       << name;
> > > +             return {};
> > > +     }
> > > +
> > > +     UniqueFD allocFd(alloc.fd);
> > > +     ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name);
> > > +     if (ret < 0) {
> > > +             LOG(HeapAllocator, Error) << "DmaHeap naming failure for
> "
> > > +                                       << name;
> > > +             return {};
> > > +     }
> > > +
> > > +     return allocFd;
> > > +}
> > > +
> > > +HeapAllocator::HeapAllocator()
> > > +{
> > > +     heap_ = std::make_unique<DmaHeap>();
> > > +}
> > > +
> > > +HeapAllocator::~HeapAllocator() = default;
> > > +
> > > +bool HeapAllocator::isValid() const
> > > +{
> > > +     return heap_->isValid();
> > > +}
> > > +
> > > +UniqueFD HeapAllocator::alloc(const char *name, std::size_t size)
> > > +{
> > > +     if (!isValid()) {
> > > +             LOG(HeapAllocator, Fatal) << "Allocation attempted
> without allocator" << name;
> > > +             return {};
> > > +     }
> > > +
> > > +     return heap_->alloc(name, size);
> > > +}
> > > +
> > > +} /* namespace libcamera */
> > > diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
> > > index d4385041..aa2d32a0 100644
> > > --- a/src/libcamera/meson.build
> > > +++ b/src/libcamera/meson.build
> > > @@ -22,6 +22,7 @@ libcamera_sources = files([
> > >      'framebuffer.cpp',
> > >      'framebuffer_allocator.cpp',
> > >      'geometry.cpp',
> > > +    'heap_allocator.cpp',
> > >      'ipa_controls.cpp',
> > >      'ipa_data_serializer.cpp',
> > >      'ipa_interface.cpp',
> > > diff --git a/src/libcamera/pipeline/meson.build
> b/src/libcamera/pipeline/meson.build
> > > index 8a61991c..b6160d34 100644
> > > --- a/src/libcamera/pipeline/meson.build
> > > +++ b/src/libcamera/pipeline/meson.build
> > > @@ -12,9 +12,6 @@ foreach pipeline : pipelines
> > >          continue
> > >      endif
> > >
> > > -    subdirs += pipeline
> > >      subdir(pipeline)
> > > -
> > > -    # Don't reuse the pipeline variable below, the subdirectory may
> have
> > > -    # overwritten it.
> > > +    subdirs += pipeline
> >
> > The comment you removed says exactly not to do this :)
> >
> > Why do you need this change ?
>
> I presume this is just a bad merge conflict ?
>
>
Yeah Kieran guess it right... Fixed.


> >
> >
> > >  endforeach
> > > diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
> b/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
> > > deleted file mode 100644
> > > index 317b1fc1..00000000
> > > --- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
> > > +++ /dev/null
> > > @@ -1,90 +0,0 @@
> > > -/* SPDX-License-Identifier: LGPL-2.1-or-later */
> > > -/*
> > > - * Copyright (C) 2020, Raspberry Pi Ltd
> > > - *
> > > - * dma_heaps.h - Helper class for dma-heap allocations.
> > > - */
> > > -
> > > -#include "dma_heaps.h"
> > > -
> > > -#include <array>
> > > -#include <fcntl.h>
> > > -#include <linux/dma-buf.h>
> > > -#include <linux/dma-heap.h>
> > > -#include <sys/ioctl.h>
> > > -#include <unistd.h>
> > > -
> > > -#include <libcamera/base/log.h>
> > > -
> > > -/*
> > > - * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows
> dmaheap-cma
> > > - * to only have to worry about importing.
> > > - *
> > > - * Annoyingly, should the cma heap size be specified on the kernel
> command line
> > > - * instead of DT, the heap gets named "reserved" instead.
> > > - */
> > > -static constexpr std::array<const char *, 2> heapNames = {
> > > -     "/dev/dma_heap/linux,cma",
> > > -     "/dev/dma_heap/reserved"
> > > -};
> > > -
> > > -namespace libcamera {
> > > -
> > > -LOG_DECLARE_CATEGORY(RPI)
> > > -
> > > -namespace RPi {
> > > -
> > > -DmaHeap::DmaHeap()
> > > -{
> > > -     for (const char *name : heapNames) {
> > > -             int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
> > > -             if (ret < 0) {
> > > -                     ret = errno;
> > > -                     LOG(RPI, Debug) << "Failed to open " << name <<
> ": "
> > > -                                     << strerror(ret);
> > > -                     continue;
> > > -             }
> > > -
> > > -             dmaHeapHandle_ = UniqueFD(ret);
> > > -             break;
> > > -     }
> > > -
> > > -     if (!dmaHeapHandle_.isValid())
> > > -             LOG(RPI, Error) << "Could not open any dmaHeap device";
> > > -}
> > > -
> > > -DmaHeap::~DmaHeap() = default;
> > > -
> > > -UniqueFD DmaHeap::alloc(const char *name, std::size_t size)
> > > -{
> > > -     int ret;
> > > -
> > > -     if (!name)
> > > -             return {};
> > > -
> > > -     struct dma_heap_allocation_data alloc = {};
> > > -
> > > -     alloc.len = size;
> > > -     alloc.fd_flags = O_CLOEXEC | O_RDWR;
> > > -
> > > -     ret = ::ioctl(dmaHeapHandle_.get(), DMA_HEAP_IOCTL_ALLOC,
> &alloc);
> > > -     if (ret < 0) {
> > > -             LOG(RPI, Error) << "dmaHeap allocation failure for "
> > > -                             << name;
> > > -             return {};
> > > -     }
> > > -
> > > -     UniqueFD allocFd(alloc.fd);
> > > -     ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name);
> > > -     if (ret < 0) {
> > > -             LOG(RPI, Error) << "dmaHeap naming failure for "
> > > -                             << name;
> > > -             return {};
> > > -     }
> > > -
> > > -     return allocFd;
> > > -}
> > > -
> > > -} /* namespace RPi */
> > > -
> > > -} /* namespace libcamera */
> > > diff --git a/src/libcamera/pipeline/rpi/vc4/meson.build
> b/src/libcamera/pipeline/rpi/vc4/meson.build
> > > index cdb049c5..b2b79735 100644
> > > --- a/src/libcamera/pipeline/rpi/vc4/meson.build
> > > +++ b/src/libcamera/pipeline/rpi/vc4/meson.build
> > > @@ -1,8 +1,5 @@
> > >  # SPDX-License-Identifier: CC0-1.0
> > >
> > > -libcamera_sources += files([
> > > -    'dma_heaps.cpp',
> > > -    'vc4.cpp',
> > > -])
> > > +libcamera_sources += files(['vc4.cpp'])
> > >
> > >  subdir('data')
> > > diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > > index 018cf488..410ecfaf 100644
> > > --- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > > +++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
> > > @@ -12,12 +12,11 @@
> > >  #include <libcamera/formats.h>
> > >
> > >  #include "libcamera/internal/device_enumerator.h"
> > > +#include "libcamera/internal/heap_allocator.h"
> > >
> > >  #include "../common/pipeline_base.h"
> > >  #include "../common/rpi_stream.h"
> > >
> > > -#include "dma_heaps.h"
> > > -
> > >  using namespace std::chrono_literals;
> > >
> > >  namespace libcamera {
> > > @@ -87,7 +86,7 @@ public:
> > >       RPi::Device<Isp, 4> isp_;
> > >
> > >       /* DMAHEAP allocation helper. */
> > > -     RPi::DmaHeap dmaHeap_;
> > > +     HeapAllocator heapAllocator_;
> > >       SharedFD lsTable_;
> > >
> > >       struct Config {
> > > @@ -296,7 +295,7 @@ int
> PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer
> > >  {
> > >       Vc4CameraData *data = static_cast<Vc4CameraData
> *>(cameraData.get());
> > >
> > > -     if (!data->dmaHeap_.isValid())
> > > +     if (!data->heapAllocator_.isValid())
> > >               return -ENOMEM;
> > >
> > >       MediaEntity *unicamImage =
> unicam->getEntityByName("unicam-image");
> > > @@ -670,9 +669,9 @@ int
> Vc4CameraData::platformConfigureIpa(ipa::RPi::ConfigParams &params)
> > >  {
> > >       params.ispControls = isp_[Isp::Input].dev()->controls();
> > >
> > > -     /* Allocate the lens shading table via dmaHeap and pass to the
> IPA. */
> > > +     /* Allocate the lens shading table via heapAllocator and pass to
> the IPA. */
> > >       if (!lsTable_.isValid()) {
> > > -             lsTable_ = SharedFD(dmaHeap_.alloc("ls_grid",
> ipa::RPi::MaxLsGridSize));
> > > +             lsTable_ = SharedFD(heapAllocator_.alloc("ls_grid",
> ipa::RPi::MaxLsGridSize));
> > >               if (!lsTable_.isValid())
> > >                       return -ENOMEM;
> > >
> > > --
> > > 2.40.1.606.ga4b1b128d6-goog
> > >
>

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h b/include/libcamera/internal/heap_allocator.h
similarity index 50%
rename from src/libcamera/pipeline/rpi/vc4/dma_heaps.h
rename to include/libcamera/internal/heap_allocator.h
index 0a4a8d86..d061fdce 100644
--- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.h
+++ b/include/libcamera/internal/heap_allocator.h
@@ -1,8 +1,8 @@ 
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 /*
- * Copyright (C) 2020, Raspberry Pi Ltd
+ * Copyright (C) 2023, Google Inc.
  *
- * dma_heaps.h - Helper class for dma-heap allocations.
+ * heap_allocator.h - Helper class for heap buffer allocations.
  */
 
 #pragma once
@@ -13,20 +13,18 @@ 
 
 namespace libcamera {
 
-namespace RPi {
+class Heap;
 
-class DmaHeap
+class HeapAllocator
 {
 public:
-	DmaHeap();
-	~DmaHeap();
-	bool isValid() const { return dmaHeapHandle_.isValid(); }
+	HeapAllocator();
+	~HeapAllocator();
+	bool isValid() const;
 	UniqueFD alloc(const char *name, std::size_t size);
 
 private:
-	UniqueFD dmaHeapHandle_;
+	std::unique_ptr<Heap> heap_;
 };
 
-} /* namespace RPi */
-
 } /* namespace libcamera */
diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
index d7508805..9d25c289 100644
--- a/include/libcamera/internal/meson.build
+++ b/include/libcamera/internal/meson.build
@@ -26,6 +26,7 @@  libcamera_internal_headers = files([
     'device_enumerator_udev.h',
     'formats.h',
     'framebuffer.h',
+    'heap_allocator.h',
     'ipa_manager.h',
     'ipa_module.h',
     'ipa_proxy.h',
diff --git a/src/libcamera/heap_allocator.cpp b/src/libcamera/heap_allocator.cpp
new file mode 100644
index 00000000..e9476de5
--- /dev/null
+++ b/src/libcamera/heap_allocator.cpp
@@ -0,0 +1,128 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Raspberry Pi Ltd
+ *
+ * heap_allocator.cpp - Helper class for heap buffer allocations.
+ */
+
+#include "libcamera/internal/heap_allocator.h"
+
+#include <array>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <linux/dma-buf.h>
+#include <linux/dma-heap.h>
+
+#include <libcamera/base/log.h>
+
+namespace libcamera {
+
+/*
+ * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma
+ * to only have to worry about importing.
+ *
+ * Annoyingly, should the cma heap size be specified on the kernel command line
+ * instead of DT, the heap gets named "reserved" instead.
+ */
+static constexpr std::array<const char *, 2> dmaHeapNames = {
+	"/dev/dma_heap/linux,cma",
+	"/dev/dma_heap/reserved"
+};
+
+LOG_DEFINE_CATEGORY(HeapAllocator)
+
+class Heap
+{
+public:
+	virtual ~Heap() = default;
+	bool isValid() const { return handle_.isValid(); }
+	virtual UniqueFD alloc(const char *name, std::size_t size) = 0;
+
+protected:
+	UniqueFD handle_;
+};
+
+class DmaHeap : public Heap
+{
+public:
+	DmaHeap();
+	~DmaHeap();
+	UniqueFD alloc(const char *name, std::size_t size) override;
+};
+
+DmaHeap::DmaHeap()
+{
+	for (const char *name : dmaHeapNames) {
+		int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
+		if (ret < 0) {
+			ret = errno;
+			LOG(HeapAllocator, Debug) << "DmaHeap failed to open " << name << ": "
+						  << strerror(ret);
+			continue;
+		}
+
+		handle_ = UniqueFD(ret);
+		break;
+	}
+
+	if (!handle_.isValid())
+		LOG(HeapAllocator, Error) << "DmaHeap could not open any dmaHeap device";
+}
+
+DmaHeap::~DmaHeap() = default;
+
+UniqueFD DmaHeap::alloc(const char *name, std::size_t size)
+{
+	int ret;
+
+	if (!name)
+		return {};
+
+	struct dma_heap_allocation_data alloc = {};
+
+	alloc.len = size;
+	alloc.fd_flags = O_CLOEXEC | O_RDWR;
+
+	ret = ::ioctl(handle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc);
+	if (ret < 0) {
+		LOG(HeapAllocator, Error) << "DmaHeap allocation failure for "
+					  << name;
+		return {};
+	}
+
+	UniqueFD allocFd(alloc.fd);
+	ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name);
+	if (ret < 0) {
+		LOG(HeapAllocator, Error) << "DmaHeap naming failure for "
+					  << name;
+		return {};
+	}
+
+	return allocFd;
+}
+
+HeapAllocator::HeapAllocator()
+{
+	heap_ = std::make_unique<DmaHeap>();
+}
+
+HeapAllocator::~HeapAllocator() = default;
+
+bool HeapAllocator::isValid() const
+{
+	return heap_->isValid();
+}
+
+UniqueFD HeapAllocator::alloc(const char *name, std::size_t size)
+{
+	if (!isValid()) {
+		LOG(HeapAllocator, Fatal) << "Allocation attempted without allocator" << name;
+		return {};
+	}
+
+	return heap_->alloc(name, size);
+}
+
+} /* namespace libcamera */
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index d4385041..aa2d32a0 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -22,6 +22,7 @@  libcamera_sources = files([
     'framebuffer.cpp',
     'framebuffer_allocator.cpp',
     'geometry.cpp',
+    'heap_allocator.cpp',
     'ipa_controls.cpp',
     'ipa_data_serializer.cpp',
     'ipa_interface.cpp',
diff --git a/src/libcamera/pipeline/meson.build b/src/libcamera/pipeline/meson.build
index 8a61991c..b6160d34 100644
--- a/src/libcamera/pipeline/meson.build
+++ b/src/libcamera/pipeline/meson.build
@@ -12,9 +12,6 @@  foreach pipeline : pipelines
         continue
     endif
 
-    subdirs += pipeline
     subdir(pipeline)
-
-    # Don't reuse the pipeline variable below, the subdirectory may have
-    # overwritten it.
+    subdirs += pipeline
 endforeach
diff --git a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp b/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
deleted file mode 100644
index 317b1fc1..00000000
--- a/src/libcamera/pipeline/rpi/vc4/dma_heaps.cpp
+++ /dev/null
@@ -1,90 +0,0 @@ 
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2020, Raspberry Pi Ltd
- *
- * dma_heaps.h - Helper class for dma-heap allocations.
- */
-
-#include "dma_heaps.h"
-
-#include <array>
-#include <fcntl.h>
-#include <linux/dma-buf.h>
-#include <linux/dma-heap.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include <libcamera/base/log.h>
-
-/*
- * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma
- * to only have to worry about importing.
- *
- * Annoyingly, should the cma heap size be specified on the kernel command line
- * instead of DT, the heap gets named "reserved" instead.
- */
-static constexpr std::array<const char *, 2> heapNames = {
-	"/dev/dma_heap/linux,cma",
-	"/dev/dma_heap/reserved"
-};
-
-namespace libcamera {
-
-LOG_DECLARE_CATEGORY(RPI)
-
-namespace RPi {
-
-DmaHeap::DmaHeap()
-{
-	for (const char *name : heapNames) {
-		int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
-		if (ret < 0) {
-			ret = errno;
-			LOG(RPI, Debug) << "Failed to open " << name << ": "
-					<< strerror(ret);
-			continue;
-		}
-
-		dmaHeapHandle_ = UniqueFD(ret);
-		break;
-	}
-
-	if (!dmaHeapHandle_.isValid())
-		LOG(RPI, Error) << "Could not open any dmaHeap device";
-}
-
-DmaHeap::~DmaHeap() = default;
-
-UniqueFD DmaHeap::alloc(const char *name, std::size_t size)
-{
-	int ret;
-
-	if (!name)
-		return {};
-
-	struct dma_heap_allocation_data alloc = {};
-
-	alloc.len = size;
-	alloc.fd_flags = O_CLOEXEC | O_RDWR;
-
-	ret = ::ioctl(dmaHeapHandle_.get(), DMA_HEAP_IOCTL_ALLOC, &alloc);
-	if (ret < 0) {
-		LOG(RPI, Error) << "dmaHeap allocation failure for "
-				<< name;
-		return {};
-	}
-
-	UniqueFD allocFd(alloc.fd);
-	ret = ::ioctl(allocFd.get(), DMA_BUF_SET_NAME, name);
-	if (ret < 0) {
-		LOG(RPI, Error) << "dmaHeap naming failure for "
-				<< name;
-		return {};
-	}
-
-	return allocFd;
-}
-
-} /* namespace RPi */
-
-} /* namespace libcamera */
diff --git a/src/libcamera/pipeline/rpi/vc4/meson.build b/src/libcamera/pipeline/rpi/vc4/meson.build
index cdb049c5..b2b79735 100644
--- a/src/libcamera/pipeline/rpi/vc4/meson.build
+++ b/src/libcamera/pipeline/rpi/vc4/meson.build
@@ -1,8 +1,5 @@ 
 # SPDX-License-Identifier: CC0-1.0
 
-libcamera_sources += files([
-    'dma_heaps.cpp',
-    'vc4.cpp',
-])
+libcamera_sources += files(['vc4.cpp'])
 
 subdir('data')
diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
index 018cf488..410ecfaf 100644
--- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
+++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
@@ -12,12 +12,11 @@ 
 #include <libcamera/formats.h>
 
 #include "libcamera/internal/device_enumerator.h"
+#include "libcamera/internal/heap_allocator.h"
 
 #include "../common/pipeline_base.h"
 #include "../common/rpi_stream.h"
 
-#include "dma_heaps.h"
-
 using namespace std::chrono_literals;
 
 namespace libcamera {
@@ -87,7 +86,7 @@  public:
 	RPi::Device<Isp, 4> isp_;
 
 	/* DMAHEAP allocation helper. */
-	RPi::DmaHeap dmaHeap_;
+	HeapAllocator heapAllocator_;
 	SharedFD lsTable_;
 
 	struct Config {
@@ -296,7 +295,7 @@  int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer
 {
 	Vc4CameraData *data = static_cast<Vc4CameraData *>(cameraData.get());
 
-	if (!data->dmaHeap_.isValid())
+	if (!data->heapAllocator_.isValid())
 		return -ENOMEM;
 
 	MediaEntity *unicamImage = unicam->getEntityByName("unicam-image");
@@ -670,9 +669,9 @@  int Vc4CameraData::platformConfigureIpa(ipa::RPi::ConfigParams &params)
 {
 	params.ispControls = isp_[Isp::Input].dev()->controls();
 
-	/* Allocate the lens shading table via dmaHeap and pass to the IPA. */
+	/* Allocate the lens shading table via heapAllocator and pass to the IPA. */
 	if (!lsTable_.isValid()) {
-		lsTable_ = SharedFD(dmaHeap_.alloc("ls_grid", ipa::RPi::MaxLsGridSize));
+		lsTable_ = SharedFD(heapAllocator_.alloc("ls_grid", ipa::RPi::MaxLsGridSize));
 		if (!lsTable_.isValid())
 			return -ENOMEM;