[libcamera-devel] [PATCH/RFC v2 4/4] ipa: Allow short-circuiting the ipa_context_ops

Laurent Pinchart laurent.pinchart at ideasonboard.com
Sun Oct 13 02:13:40 CEST 2019


When an IPA module is loaded without isolation and implements the
IPAInterface internally, going through ipa_context_ops is a waste of
time. Add an operation to retrieve the IPAInterface, and use it directly
in the IPAContextWrapper.

Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
---
 include/ipa/ipa_interface.h                 |  1 +
 src/ipa/libipa/ipa_interface_wrapper.cpp    |  8 ++++++
 src/ipa/libipa/ipa_interface_wrapper.h      |  1 +
 src/libcamera/include/ipa_context_wrapper.h |  3 +++
 src/libcamera/ipa_context_wrapper.cpp       | 29 ++++++++++++++++++++-
 src/libcamera/ipa_interface.cpp             | 18 +++++++++++++
 6 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/include/ipa/ipa_interface.h b/include/ipa/ipa_interface.h
index acb491e3958c..c104b8805e7e 100644
--- a/include/ipa/ipa_interface.h
+++ b/include/ipa/ipa_interface.h
@@ -34,6 +34,7 @@ struct ipa_callback_ops {
 
 struct ipa_context_ops {
 	void (*destroy)(struct ipa_context *ctx);
+	void *(*get_interface)(struct ipa_context *ctx);
 	void (*init)(struct ipa_context *ctx);
 	void (*register_callbacks)(struct ipa_context *ctx,
 				   const struct ipa_callback_ops *callbacks,
diff --git a/src/ipa/libipa/ipa_interface_wrapper.cpp b/src/ipa/libipa/ipa_interface_wrapper.cpp
index d7c4905e72ee..baed3acd2b01 100644
--- a/src/ipa/libipa/ipa_interface_wrapper.cpp
+++ b/src/ipa/libipa/ipa_interface_wrapper.cpp
@@ -65,6 +65,13 @@ void IPAInterfaceWrapper::destroy(struct ipa_context *_ctx)
 	delete ctx;
 }
 
+void *IPAInterfaceWrapper::get_interface(struct ipa_context *_ctx)
+{
+	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
+
+	return ctx->ipa_;
+}
+
 void IPAInterfaceWrapper::init(struct ipa_context *_ctx)
 {
 	IPAInterfaceWrapper *ctx = static_cast<IPAInterfaceWrapper *>(_ctx);
@@ -139,6 +146,7 @@ void IPAInterfaceWrapper::queueFrameAction(unsigned int frame,
  */
 const struct ipa_context_ops IPAInterfaceWrapper::operations_ = {
 	.destroy = &IPAInterfaceWrapper::destroy,
+	.get_interface = &IPAInterfaceWrapper::get_interface,
 	.init = &IPAInterfaceWrapper::init,
 	.register_callbacks = &IPAInterfaceWrapper::register_callbacks,
 	.configure = &IPAInterfaceWrapper::configure,
diff --git a/src/ipa/libipa/ipa_interface_wrapper.h b/src/ipa/libipa/ipa_interface_wrapper.h
index a7c70cdc2d83..c4b9d4b668d8 100644
--- a/src/ipa/libipa/ipa_interface_wrapper.h
+++ b/src/ipa/libipa/ipa_interface_wrapper.h
@@ -18,6 +18,7 @@ public:
 
 private:
 	static void destroy(struct ipa_context *ctx);
+	static void *get_interface(struct ipa_context *ctx);
 	static void init(struct ipa_context *ctx);
 	static void register_callbacks(struct ipa_context *ctx,
 				       const struct ipa_callback_ops *callbacks,
diff --git a/src/libcamera/include/ipa_context_wrapper.h b/src/libcamera/include/ipa_context_wrapper.h
index f758bb07abea..218768eaa8be 100644
--- a/src/libcamera/include/ipa_context_wrapper.h
+++ b/src/libcamera/include/ipa_context_wrapper.h
@@ -30,7 +30,10 @@ private:
 	static void queue_frame_action(void *ctx, unsigned int frame);
 	static const struct ipa_callback_ops callbacks_;
 
+	void queueFrameAction(unsigned int frame, const IPAOperationData &data);
+
 	struct ipa_context *ctx_;
+	IPAInterface *intf_;
 };
 
 } /* namespace libcamera */
diff --git a/src/libcamera/ipa_context_wrapper.cpp b/src/libcamera/ipa_context_wrapper.cpp
index 355911791d43..7e58a7971391 100644
--- a/src/libcamera/ipa_context_wrapper.cpp
+++ b/src/libcamera/ipa_context_wrapper.cpp
@@ -41,6 +41,12 @@ namespace libcamera {
 IPAContextWrapper::IPAContextWrapper(struct ipa_context *context)
 	: ctx_(context)
 {
+	if (ctx_ && ctx_->ops->get_interface) {
+		intf_ = reinterpret_cast<IPAInterface *>(ctx_->ops->get_interface(ctx_));
+		intf_->queueFrameAction.connect(this, &IPAContextWrapper::queueFrameAction);
+	} else {
+		intf_ = nullptr;
+	}
 }
 
 IPAContextWrapper::~IPAContextWrapper()
@@ -51,6 +57,9 @@ IPAContextWrapper::~IPAContextWrapper()
 
 int IPAContextWrapper::init()
 {
+	if (intf_)
+		return intf_->init();
+
 	if (!ctx_)
 		return 0;
 
@@ -63,6 +72,9 @@ int IPAContextWrapper::init()
 void IPAContextWrapper::configure(const std::map<unsigned int, IPAStream> &streamConfig,
 				  const std::map<unsigned int, V4L2ControlInfoMap> &entityControls)
 {
+	if (intf_)
+		return intf_->configure(streamConfig, entityControls);
+
 	if (!ctx_)
 		return;
 
@@ -71,6 +83,9 @@ void IPAContextWrapper::configure(const std::map<unsigned int, IPAStream> &strea
 
 void IPAContextWrapper::mapBuffers(const std::vector<IPABuffer> &buffers)
 {
+	if (intf_)
+		return intf_->mapBuffers(buffers);
+
 	if (!ctx_)
 		return;
 
@@ -96,6 +111,9 @@ void IPAContextWrapper::mapBuffers(const std::vector<IPABuffer> &buffers)
 
 void IPAContextWrapper::unmapBuffers(const std::vector<unsigned int> &ids)
 {
+	if (intf_)
+		return intf_->unmapBuffers(ids);
+
 	if (!ctx_)
 		return;
 
@@ -104,18 +122,27 @@ void IPAContextWrapper::unmapBuffers(const std::vector<unsigned int> &ids)
 
 void IPAContextWrapper::processEvent(const IPAOperationData &data)
 {
+	if (intf_)
+		return intf_->processEvent(data);
+
 	if (!ctx_)
 		return;
 
 	ctx_->ops->process_event(ctx_);
 }
 
+void IPAContextWrapper::queueFrameAction(unsigned int frame,
+					 const IPAOperationData &data)
+{
+	IPAInterface::queueFrameAction.emit(frame, data);
+}
+
 void IPAContextWrapper::queue_frame_action(void *ctx, unsigned int frame)
 {
 	IPAContextWrapper *_this = static_cast<IPAContextWrapper *>(ctx);
 	IPAOperationData data;
 
-	_this->queueFrameAction.emit(frame, data);
+	_this->queueFrameAction(frame, data);
 }
 
 #ifndef __DOXYGEN__
diff --git a/src/libcamera/ipa_interface.cpp b/src/libcamera/ipa_interface.cpp
index 1df430d721f0..a0647b112466 100644
--- a/src/libcamera/ipa_interface.cpp
+++ b/src/libcamera/ipa_interface.cpp
@@ -62,6 +62,12 @@
  * handlers to communicate with IPA modules. IPA modules may use the
  * IPAInterface API internally if they want to benefit from the data and helper
  * classes offered by libcamera.
+ *
+ * When an IPA module is loaded directly into the libcamera process and uses
+ * the IPAInterface API internally, short-circuiting the path to the
+ * ipa_context_ops and back to IPAInterface is desirable. To support this, IPA
+ * modules may implement the ipa_context_ops::get_interface function to return a
+ * pointer to their internal IPAInterface.
  */
 
 /**
@@ -146,6 +152,18 @@
  * \param[in] ctx The IPA context
  */
 
+/**
+ * \var ipa_context_ops::get_interface
+ * \brief Retrieve the IPAInterface implemented by the ipa_context (optional)
+ * \param[in] ctx The IPA context
+ *
+ * IPA modules may implement this function to expose their internal
+ * IPAInterface, if any. When implemented, libcamera may at its sole discretion
+ * call it and then bypass the ipa_context_ops API by calling the IPAInterface
+ * methods directly. IPA modules shall still implement and support the full
+ * ipa_context_ops API.
+ */
+
 /**
  * \var ipa_context_ops::init
  * \brief Initialise the IPA context
-- 
Regards,

Laurent Pinchart



More information about the libcamera-devel mailing list