[libcamera-devel] Remove limitation that camera and display must match
diff mbox series

Message ID 20220204111254.22884-1-ecurtin@redhat.com
State Superseded
Headers show
Series
  • [libcamera-devel] Remove limitation that camera and display must match
Related show

Commit Message

Eric Curtin Feb. 4, 2022, 11:12 a.m. UTC
There is a limitation that requires input and output
to be pixel for pixel identical in terms of height
and width. Remove this limitation to enable more
hardware that doesn't match. Centralize the image.

Signed-off-by: Eric Curtin <ecurtin@redhat.com>
---
 src/cam/kms_sink.cpp | 27 +++++++++------------------
 src/cam/kms_sink.h   |  2 ++
 2 files changed, 11 insertions(+), 18 deletions(-)

Comments

Eric Curtin Feb. 4, 2022, 11:43 a.m. UTC | #1
On Fri, 4 Feb 2022 at 11:13, Eric Curtin <ecurtin@redhat.com> wrote:
>
> There is a limitation that requires input and output
> to be pixel for pixel identical in terms of height
> and width. Remove this limitation to enable more
> hardware that doesn't match. Centralize the image.
>
> Signed-off-by: Eric Curtin <ecurtin@redhat.com>
> ---
>  src/cam/kms_sink.cpp | 27 +++++++++------------------
>  src/cam/kms_sink.h   |  2 ++
>  2 files changed, 11 insertions(+), 18 deletions(-)
>
> diff --git a/src/cam/kms_sink.cpp b/src/cam/kms_sink.cpp
> index 973cd370..159b9355 100644
> --- a/src/cam/kms_sink.cpp
> +++ b/src/cam/kms_sink.cpp
> @@ -113,24 +113,15 @@ int KMSSink::configure(const libcamera::CameraConfiguration &config)
>         const libcamera::StreamConfiguration &cfg = config.at(0);
>
>         const std::vector<DRM::Mode> &modes = connector_->modes();
> -       const auto iter = std::find_if(modes.begin(), modes.end(),
> -                                      [&](const DRM::Mode &mode) {
> -                                              return mode.hdisplay == cfg.size.width &&
> -                                                     mode.vdisplay == cfg.size.height;
> -                                      });
> -       if (iter == modes.end()) {
> -               std::cerr
> -                       << "No mode matching " << cfg.size.toString()
> -                       << std::endl;
> -               return -EINVAL;
> -       }
>
>         int ret = configurePipeline(cfg.pixelFormat);
>         if (ret < 0)
>                 return ret;
>
> -       mode_ = &*iter;
> +       mode_ = &modes[0];
>         size_ = cfg.size;
> +       x_ = (mode_->hdisplay - size_.width) / 2;
> +       y_ = (mode_->vdisplay - size_.height) / 2;
>         stride_ = cfg.stride;
>
>         return 0;
> @@ -297,12 +288,12 @@ bool KMSSink::processRequest(libcamera::Request *camRequest)
>                 drmRequest->addProperty(plane_, "CRTC_ID", crtc_->id());
>                 drmRequest->addProperty(plane_, "SRC_X", 0 << 16);
>                 drmRequest->addProperty(plane_, "SRC_Y", 0 << 16);
> -               drmRequest->addProperty(plane_, "SRC_W", mode_->hdisplay << 16);
> -               drmRequest->addProperty(plane_, "SRC_H", mode_->vdisplay << 16);
> -               drmRequest->addProperty(plane_, "CRTC_X", 0);
> -               drmRequest->addProperty(plane_, "CRTC_Y", 0);
> -               drmRequest->addProperty(plane_, "CRTC_W", mode_->hdisplay);
> -               drmRequest->addProperty(plane_, "CRTC_H", mode_->vdisplay);
> +               drmRequest->addProperty(plane_, "SRC_W", size_.width << 16);
> +               drmRequest->addProperty(plane_, "SRC_H", size_.height << 16);
> +               drmRequest->addProperty(plane_, "CRTC_X", x_);
> +               drmRequest->addProperty(plane_, "CRTC_Y", y_);
> +               drmRequest->addProperty(plane_, "CRTC_W", size_.width);
> +               drmRequest->addProperty(plane_, "CRTC_H", size_.height);
>
>                 flags |= DRM::AtomicRequest::FlagAllowModeset;
>         }
> diff --git a/src/cam/kms_sink.h b/src/cam/kms_sink.h
> index 4a0a872c..1b08e887 100644
> --- a/src/cam/kms_sink.h
> +++ b/src/cam/kms_sink.h
> @@ -61,6 +61,8 @@ private:
>         libcamera::PixelFormat format_;
>         libcamera::Size size_;
>         unsigned int stride_;
> +       unsigned int x_;  // Where to start drawing camera output
> +       unsigned int y_;  // Where to start drawing camera output
>
>         std::map<libcamera::FrameBuffer *, std::unique_ptr<DRM::FrameBuffer>> buffers_;
>
> --
> 2.34.1
>

Might require a follow on commit for the larger camera resolution on
smaller display case, if DRM allows you to write to negative pixels,
it might just work to change those unsigned ints to signed ints. Not a
scenario I come across on my hardware.

Patch
diff mbox series

diff --git a/src/cam/kms_sink.cpp b/src/cam/kms_sink.cpp
index 973cd370..159b9355 100644
--- a/src/cam/kms_sink.cpp
+++ b/src/cam/kms_sink.cpp
@@ -113,24 +113,15 @@  int KMSSink::configure(const libcamera::CameraConfiguration &config)
 	const libcamera::StreamConfiguration &cfg = config.at(0);
 
 	const std::vector<DRM::Mode> &modes = connector_->modes();
-	const auto iter = std::find_if(modes.begin(), modes.end(),
-				       [&](const DRM::Mode &mode) {
-					       return mode.hdisplay == cfg.size.width &&
-						      mode.vdisplay == cfg.size.height;
-				       });
-	if (iter == modes.end()) {
-		std::cerr
-			<< "No mode matching " << cfg.size.toString()
-			<< std::endl;
-		return -EINVAL;
-	}
 
 	int ret = configurePipeline(cfg.pixelFormat);
 	if (ret < 0)
 		return ret;
 
-	mode_ = &*iter;
+	mode_ = &modes[0];
 	size_ = cfg.size;
+	x_ = (mode_->hdisplay - size_.width) / 2;
+	y_ = (mode_->vdisplay - size_.height) / 2;
 	stride_ = cfg.stride;
 
 	return 0;
@@ -297,12 +288,12 @@  bool KMSSink::processRequest(libcamera::Request *camRequest)
 		drmRequest->addProperty(plane_, "CRTC_ID", crtc_->id());
 		drmRequest->addProperty(plane_, "SRC_X", 0 << 16);
 		drmRequest->addProperty(plane_, "SRC_Y", 0 << 16);
-		drmRequest->addProperty(plane_, "SRC_W", mode_->hdisplay << 16);
-		drmRequest->addProperty(plane_, "SRC_H", mode_->vdisplay << 16);
-		drmRequest->addProperty(plane_, "CRTC_X", 0);
-		drmRequest->addProperty(plane_, "CRTC_Y", 0);
-		drmRequest->addProperty(plane_, "CRTC_W", mode_->hdisplay);
-		drmRequest->addProperty(plane_, "CRTC_H", mode_->vdisplay);
+		drmRequest->addProperty(plane_, "SRC_W", size_.width << 16);
+		drmRequest->addProperty(plane_, "SRC_H", size_.height << 16);
+		drmRequest->addProperty(plane_, "CRTC_X", x_);
+		drmRequest->addProperty(plane_, "CRTC_Y", y_);
+		drmRequest->addProperty(plane_, "CRTC_W", size_.width);
+		drmRequest->addProperty(plane_, "CRTC_H", size_.height);
 
 		flags |= DRM::AtomicRequest::FlagAllowModeset;
 	}
diff --git a/src/cam/kms_sink.h b/src/cam/kms_sink.h
index 4a0a872c..1b08e887 100644
--- a/src/cam/kms_sink.h
+++ b/src/cam/kms_sink.h
@@ -61,6 +61,8 @@  private:
 	libcamera::PixelFormat format_;
 	libcamera::Size size_;
 	unsigned int stride_;
+	unsigned int x_;  // Where to start drawing camera output
+	unsigned int y_;  // Where to start drawing camera output
 
 	std::map<libcamera::FrameBuffer *, std::unique_ptr<DRM::FrameBuffer>> buffers_;