From patchwork Mon Jan 13 16:42:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 2630 X-Patchwork-Delegate: jacopo@jmondi.org Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EA66A60728 for ; Mon, 13 Jan 2020 17:40:35 +0100 (CET) Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 757CB100005; Mon, 13 Jan 2020 16:40:35 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Mon, 13 Jan 2020 17:42:37 +0100 Message-Id: <20200113164245.52535-16-jacopo@jmondi.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200113164245.52535-1-jacopo@jmondi.org> References: <20200113164245.52535-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 15/23] libcamera: controls: Support compound controls in ControlValue X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Jan 2020 16:40:37 -0000 Add compound controls support to the ControlValue class. The polymorphic class can now store more than a single element and supports access and creation through the use of Span<>. Signed-off-by: Jacopo Mondi --- include/libcamera/controls.h | 37 +++- src/libcamera/controls.cpp | 329 ++++++++++++++++++++++++++++++++--- 2 files changed, 333 insertions(+), 33 deletions(-) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 8fa33d93b088..bdbdb213528d 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -11,6 +11,8 @@ #include #include +#include + namespace libcamera { class ControlValidator; @@ -21,6 +23,10 @@ enum ControlType { ControlTypeInteger32, ControlTypeInteger64, ControlTypeFloat, + ControlTypeCompoundBool, + ControlTypeCompoundInt32, + ControlTypeCompoundInt64, + ControlTypeCompoundFloat, }; class ControlValue @@ -31,12 +37,18 @@ public: ControlValue(int32_t value); ControlValue(int64_t value); ControlValue(float value); + ControlValue(Span &values); + ControlValue(Span &values); + ControlValue(Span &values); + ControlValue(Span &values); + ~ControlValue(); ControlType type() const { return type_; } bool isNone() const { return type_ == ControlTypeNone; } + std::size_t numElements() const { return numElements_; } template - const T &get() const; + T get() const; template void set(const T &value); @@ -57,6 +69,21 @@ private: int64_t integer64_; float float_; }; + + union { + void *pvoid_; + bool *pbool_; + int32_t *p32_; + int64_t *p64_; + float *pfloat_; + }; + + std::size_t numElements_; + + void release(); + bool compareElement(const ControlValue &other) const; + bool compareElement(const ControlValue &other, unsigned int i) const; + std::string elemToString(unsigned int i) const; }; class ControlId @@ -215,13 +242,11 @@ public: bool contains(unsigned int id) const; template - const T &get(const Control &ctrl) const + const T get(const Control &ctrl) const { const ControlValue *val = find(ctrl.id()); - if (!val) { - static T t(0); - return t; - } + if (!val) + return T{}; return val->get(); } diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 74ce5d0ba4f1..7718a53911e6 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -9,7 +9,9 @@ #include #include -#include +#include + +#include #include "control_validator.h" #include "log.h" @@ -60,6 +62,14 @@ LOG_DEFINE_CATEGORY(Controls) * The control stores a 64-bit integer value * \var ControlTypeFloat * The control stores a 32-bit floating point value + * \var ControlTypeCompoundBool + * The control stores an array of boolean values + * \var ControlTypeCompoundInt32 + * The control stores an array of 32-bit integer values + * \var ControlTypeCompoundInt64 + * The control stores an array of 64-bit integer values + * \var ControlTypeCompoundFloat + * The control stores an array of 32-bit floating values */ /** @@ -71,7 +81,7 @@ LOG_DEFINE_CATEGORY(Controls) * \brief Construct an empty ControlValue. */ ControlValue::ControlValue() - : type_(ControlTypeNone) + : type_(ControlTypeNone), pvoid_(nullptr), numElements_(0) { } @@ -80,7 +90,8 @@ ControlValue::ControlValue() * \param[in] value Boolean value to store */ ControlValue::ControlValue(bool value) - : type_(ControlTypeBool), bool_(value) + : type_(ControlTypeBool), bool_(value), pvoid_(nullptr), + numElements_(1) { } @@ -89,7 +100,8 @@ ControlValue::ControlValue(bool value) * \param[in] value Integer value to store */ ControlValue::ControlValue(int32_t value) - : type_(ControlTypeInteger32), integer32_(value) + : type_(ControlTypeInteger32), integer32_(value), pvoid_(nullptr), + numElements_(1) { } @@ -98,7 +110,8 @@ ControlValue::ControlValue(int32_t value) * \param[in] value Integer value to store */ ControlValue::ControlValue(int64_t value) - : type_(ControlTypeInteger64), integer64_(value) + : type_(ControlTypeInteger64), integer64_(value), pvoid_(nullptr), + numElements_(1) { } @@ -107,8 +120,73 @@ ControlValue::ControlValue(int64_t value) * \param[in] value Float value to store */ ControlValue::ControlValue(float value) - : type_(ControlTypeFloat), float_(value) + : type_(ControlTypeFloat), float_(value), pvoid_(nullptr), + numElements_(1) +{ +} + +/** + * \brief Construct a ControlValue with a Span of boolean elements + * \param[in] values Span of boolean values to store + */ +ControlValue::ControlValue(Span &values) + : type_(ControlTypeCompoundBool), numElements_(values.size()) { + pbool_ = new bool[numElements_]; + memcpy(pbool_, values.data(), sizeof(bool) * numElements_); +} + +/** + * \brief Construct a ControlValue with a Span of 32 bit integers elements + * \param[in] values Span of 32 bit integer values to store + */ +ControlValue::ControlValue(Span &values) + : type_(ControlTypeCompoundInt32), numElements_(values.size()) +{ + p32_ = new int32_t[numElements_]; + memcpy(p32_, values.data(), sizeof(int32_t) * numElements_); +} + +/** + * \brief Construct a ControlValue with a Span of 64 bit integers elements + * \param[in] values Span of 64 bit integer values to store + */ +ControlValue::ControlValue(Span &values) + : type_(ControlTypeCompoundInt64), numElements_(values.size()) +{ + p64_ = new int64_t[numElements_]; + memcpy(p64_, values.data(), sizeof(int64_t) * numElements_); +} + +/** + * \brief Construct a ControlValue with a Span of float elements + * \param[in] values Span of float values to store + */ +ControlValue::ControlValue(Span &values) + : type_(ControlTypeCompoundFloat), numElements_(values.size()) +{ + pfloat_ = new float[numElements_]; + memcpy(pfloat_, values.data(), sizeof(float) * numElements_); +} + +void ControlValue::release() +{ + switch (type_) { + case ControlTypeCompoundBool: + case ControlTypeCompoundInt32: + case ControlTypeCompoundInt64: + case ControlTypeCompoundFloat: + delete[] pbool_; + pbool_ = nullptr; + /* fall-through. */ + default: + return; + } +} + +ControlValue::~ControlValue() +{ + release(); } /** @@ -124,24 +202,38 @@ ControlValue::ControlValue(float value) */ /** - * \fn template const T &ControlValue::get() const - * \brief Get the control value + * \fn ControlValue::numElements() + * \brief Retrieve the number of elements stored in the ControlValue + * \return The number of elements stored in the ControlValue + */ + +/** + * \fn template const T ControlValue::get() const + * \brief Get the control values * * The control value type shall match the type T, otherwise the behaviour is * undefined. * - * \return The control value + * This function applies to ControlValue instances which store a single or + * multiple values. The ControlValue's elements are returned in a Span in the + * former case. + * + * \return The control value or a Span of values */ /** - * \fn template void ControlValue::set(const T &value) - * \brief Set the control value to \a value - * \param[in] value The control value + * \fn template void ControlValue::set(const T &values) + * \brief Set the control values to \a values + * \param[in] values The control values + * + * This function can be used to set the ControlValue to a single value, or + * to store multiple values by providing a Span<> of elements to the + * function. */ #ifndef __DOXYGEN__ template<> -const bool &ControlValue::get() const +bool ControlValue::get() const { ASSERT(type_ == ControlTypeBool); @@ -149,7 +241,19 @@ const bool &ControlValue::get() const } template<> -const int32_t &ControlValue::get() const +Span ControlValue::get>() const +{ + ASSERT(type_ == ControlTypeCompoundBool); + + /* + * Explicitly create a Span instance, otherwise the compiler + * tries to match with the Span class initializer_list constructor. + */ + return Span(pbool_, static_cast(numElements_)); +} + +template<> +int32_t ControlValue::get() const { ASSERT(type_ == ControlTypeInteger32 || type_ == ControlTypeInteger64); @@ -157,7 +261,16 @@ const int32_t &ControlValue::get() const } template<> -const int64_t &ControlValue::get() const +Span ControlValue::get>() const +{ + ASSERT(type_ == ControlTypeCompoundInt32 || + type_ == ControlTypeCompoundInt64); + + return { p32_, numElements_ }; +} + +template<> +int64_t ControlValue::get() const { ASSERT(type_ == ControlTypeInteger32 || type_ == ControlTypeInteger64); @@ -165,62 +278,190 @@ const int64_t &ControlValue::get() const } template<> -const float &ControlValue::get() const +Span ControlValue::get>() const +{ + ASSERT(type_ == ControlTypeCompoundInt32 || + type_ == ControlTypeCompoundInt64); + + return { p64_, numElements_ }; +} + +template<> +float ControlValue::get() const { ASSERT(type_ == ControlTypeFloat); return float_; } +template<> +Span ControlValue::get>() const +{ + ASSERT(type_ == ControlTypeCompoundFloat); + + return { pfloat_, numElements_ }; +} + template<> void ControlValue::set(const bool &value) { + release(); + type_ = ControlTypeBool; bool_ = value; + numElements_ = 1; +} + +template<> +void ControlValue::set>(const Span &values) +{ + release(); + + type_ = ControlTypeCompoundBool; + numElements_ = values.size(); + + pbool_ = new bool[numElements_]; + memcpy(pbool_, values.data(), sizeof(bool) * numElements_); } template<> void ControlValue::set(const int32_t &value) { + release(); + type_ = ControlTypeInteger32; integer32_ = value; + numElements_ = 1; +} + +template<> +void ControlValue::set>(const Span &values) +{ + release(); + + type_ = ControlTypeCompoundInt32; + numElements_ = values.size(); + + p32_ = new int32_t[numElements_]; + memcpy(p32_, values.data(), sizeof(int32_t) * numElements_); } template<> void ControlValue::set(const int64_t &value) { + release(); + type_ = ControlTypeInteger64; integer64_ = value; + numElements_ = 1; +} + +template<> +void ControlValue::set>(const Span &values) +{ + release(); + + type_ = ControlTypeCompoundInt64; + numElements_ = values.size(); + + p64_ = new int64_t[numElements_]; + memcpy(p64_, values.data(), sizeof(int64_t) * numElements_); } template<> void ControlValue::set(const float &value) { + release(); + type_ = ControlTypeFloat; float_ = value; + numElements_ = 1; } + +template<> +void ControlValue::set>(const Span &values) +{ + release(); + + type_ = ControlTypeCompoundFloat; + numElements_ = values.size(); + + pfloat_ = new float[numElements_]; + memcpy(pfloat_, values.data(), sizeof(float) * numElements_); +} + #endif /* __DOXYGEN__ */ +std::string ControlValue::elemToString(unsigned int i) const +{ + switch (type_) { + case ControlTypeBool: + return bool_ ? "True " : "False "; + case ControlTypeInteger32: + return std::to_string(integer32_); + case ControlTypeInteger64: + return std::to_string(integer64_); + case ControlTypeFloat: + return std::to_string(float_); + case ControlTypeCompoundBool: + return pbool_[i] ? "True " : "False "; + case ControlTypeCompoundInt32: + return std::to_string(p32_[i]) + " "; + case ControlTypeCompoundInt64: + return std::to_string(p64_[i]) + " "; + case ControlTypeCompoundFloat: + return std::to_string(pfloat_[i]) + " "; + default: + return ""; + } +} + /** * \brief Assemble and return a string describing the value * \return A string describing the ControlValue */ std::string ControlValue::toString() const +{ + if (ControlTypeNone) + return ""; + + std::string str; + for (unsigned int i = 0; i < numElements_; ++i) + str += elemToString(i); + + return str; +} + +bool ControlValue::compareElement(const ControlValue &other) const { switch (type_) { - case ControlTypeNone: - return ""; case ControlTypeBool: - return bool_ ? "True" : "False"; + return bool_ == other.bool_; case ControlTypeInteger32: - return std::to_string(integer32_); + return integer32_ == other.integer32_; case ControlTypeInteger64: - return std::to_string(integer64_); + return integer64_ == other.integer64_; case ControlTypeFloat: - return std::to_string(float_); + return float_ == other.float_; + default: + return false; } +} - return ""; +bool ControlValue::compareElement(const ControlValue &other, unsigned int i) const +{ + switch (type_) { + case ControlTypeCompoundBool: + return pbool_[i] == other.pbool_[i]; + case ControlTypeCompoundInt32: + return p32_[i] == other.p32_[i]; + case ControlTypeCompoundInt64: + return p64_[i] == other.p64_[i]; + case ControlTypeCompoundFloat: + return pfloat_[i] == other.pfloat_[i]; + default: + return false; + } } /** @@ -232,15 +473,25 @@ bool ControlValue::operator==(const ControlValue &other) const if (type_ != other.type_) return false; + if (numElements_ != other.numElements()) + return false; + switch (type_) { case ControlTypeBool: - return bool_ == other.bool_; case ControlTypeInteger32: - return integer32_ == other.integer32_; case ControlTypeInteger64: - return integer64_ == other.integer64_; case ControlTypeFloat: - return float_ == other.float_; + return compareElement(other); + case ControlTypeCompoundBool: + case ControlTypeCompoundInt32: + case ControlTypeCompoundInt64: + case ControlTypeCompoundFloat: + for (unsigned int i = 0; i < numElements_; ++i) { + if (!compareElement(other, i)) + return false; + } + + return true; default: return false; } @@ -360,23 +611,47 @@ Control::Control(unsigned int id, const char *name) { } +template<> +Control>::Control(unsigned int id, const char *name) + : ControlId(id, name, ControlTypeCompoundBool) +{ +} + template<> Control::Control(unsigned int id, const char *name) : ControlId(id, name, ControlTypeInteger32) { } +template<> +Control>::Control(unsigned int id, const char *name) + : ControlId(id, name, ControlTypeCompoundInt32) +{ +} + template<> Control::Control(unsigned int id, const char *name) : ControlId(id, name, ControlTypeInteger64) { } +template<> +Control>::Control(unsigned int id, const char *name) + : ControlId(id, name, ControlTypeCompoundInt64) +{ +} + template<> Control::Control(unsigned int id, const char *name) : ControlId(id, name, ControlTypeFloat) { } + +template<> +Control>::Control(unsigned int id, const char *name) + : ControlId(id, name, ControlTypeCompoundFloat) +{ +} #endif /* __DOXYGEN__ */ /**