opencv_mv/QMainPro/QMacVisual/include/opencv2/gapi/gopaque.hpp

370 lines
12 KiB
C++
Raw Permalink Normal View History

2023-05-22 09:27:46 +00:00
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2019-2020 Intel Corporation
#ifndef OPENCV_GAPI_GOPAQUE_HPP
#define OPENCV_GAPI_GOPAQUE_HPP
#include <functional>
#include <ostream>
#include <memory>
#include <opencv2/gapi/own/exports.hpp>
#include <opencv2/gapi/opencv_includes.hpp>
#include <opencv2/gapi/util/any.hpp>
#include <opencv2/gapi/util/variant.hpp>
#include <opencv2/gapi/util/throw.hpp>
#include <opencv2/gapi/util/type_traits.hpp>
#include <opencv2/gapi/own/assert.hpp>
#include <opencv2/gapi/gcommon.hpp> // OpaqueKind
#include <opencv2/gapi/garray.hpp> // TypeHintBase
namespace cv
{
// Forward declaration; GNode and GOrigin are an internal
// (user-inaccessible) classes.
class GNode;
struct GOrigin;
template<typename T> class GOpaque;
/**
* \addtogroup gapi_meta_args
* @{
*/
struct GAPI_EXPORTS_W_SIMPLE GOpaqueDesc
{
// FIXME: Body
// FIXME: Also implement proper operator== then
bool operator== (const GOpaqueDesc&) const { return true; }
};
template<typename U> GOpaqueDesc descr_of(const U &) { return {};}
GAPI_EXPORTS_W inline GOpaqueDesc empty_gopaque_desc() {return {}; }
/** @} */
std::ostream& operator<<(std::ostream& os, const cv::GOpaqueDesc &desc);
namespace detail
{
// ConstructOpaque is a callback which stores information about T and is used by
// G-API runtime to construct an object in host memory (T remains opaque for G-API).
// ConstructOpaque is carried into G-API internals by GOpaqueU.
// Currently it is suitable for Host (CPU) plugins only, real offload may require
// more information for manual memory allocation on-device.
class OpaqueRef;
using ConstructOpaque = std::function<void(OpaqueRef&)>;
// FIXME: garray.hpp already contains hint classes (for actual T type verification),
// need to think where it can be moved (currently opaque uses it from garray)
// This class strips type information from GOpaque<T> and makes it usable
// in the G-API graph compiler (expression unrolling, graph generation, etc).
// Part of GProtoArg.
class GAPI_EXPORTS GOpaqueU
{
public:
GOpaqueU(const GNode &n, std::size_t out); // Operation result constructor
template <typename T>
bool holds() const; // Check if was created from GOpaque<T>
GOrigin& priv(); // Internal use only
const GOrigin& priv() const; // Internal use only
protected:
GOpaqueU(); // Default constructor
template<class> friend class cv::GOpaque; // (available for GOpaque<T> only)
void setConstructFcn(ConstructOpaque &&cv); // Store T-aware constructor
template <typename T>
void specifyType(); // Store type of initial GOpaque<T>
template <typename T>
void storeKind();
void setKind(cv::detail::OpaqueKind);
std::shared_ptr<GOrigin> m_priv;
std::shared_ptr<TypeHintBase> m_hint;
};
template <typename T>
bool GOpaqueU::holds() const{
GAPI_Assert(m_hint != nullptr);
using U = util::decay_t<T>;
return dynamic_cast<TypeHint<U>*>(m_hint.get()) != nullptr;
};
template <typename T>
void GOpaqueU::specifyType(){
m_hint.reset(new TypeHint<util::decay_t<T>>);
};
template <typename T>
void GOpaqueU::storeKind(){
// FIXME: Add assert here on cv::Mat and cv::Scalar?
setKind(cv::detail::GOpaqueTraits<T>::kind);
};
// This class represents a typed object reference.
// Depending on origins, this reference may be either "just a" reference to
// an object created externally, OR actually own the underlying object
// (be value holder).
class BasicOpaqueRef
{
public:
cv::GOpaqueDesc m_desc;
virtual ~BasicOpaqueRef() {}
virtual void mov(BasicOpaqueRef &ref) = 0;
virtual const void* ptr() const = 0;
virtual void set(const cv::util::any &a) = 0;
};
template<typename T> class OpaqueRefT final: public BasicOpaqueRef
{
using empty_t = util::monostate;
using ro_ext_t = const T *;
using rw_ext_t = T *;
using rw_own_t = T ;
util::variant<empty_t, ro_ext_t, rw_ext_t, rw_own_t> m_ref;
inline bool isEmpty() const { return util::holds_alternative<empty_t>(m_ref); }
inline bool isROExt() const { return util::holds_alternative<ro_ext_t>(m_ref); }
inline bool isRWExt() const { return util::holds_alternative<rw_ext_t>(m_ref); }
inline bool isRWOwn() const { return util::holds_alternative<rw_own_t>(m_ref); }
void init(const T* obj = nullptr)
{
if (obj) m_desc = cv::descr_of(*obj);
}
public:
OpaqueRefT() { init(); }
virtual ~OpaqueRefT() {}
explicit OpaqueRefT(const T& obj) : m_ref(&obj) { init(&obj); }
explicit OpaqueRefT( T& obj) : m_ref(&obj) { init(&obj); }
explicit OpaqueRefT( T&& obj) : m_ref(std::move(obj)) { init(&obj); }
// Reset a OpaqueRefT. Called only for objects instantiated
// internally in G-API (e.g. temporary GOpaque<T>'s within a
// computation). Reset here means both initialization
// (creating an object) and reset (discarding its existing
// content before the next execution). Must never be called
// for external OpaqueRefTs.
void reset()
{
if (isEmpty())
{
T empty_obj{};
m_desc = cv::descr_of(empty_obj);
m_ref = std::move(empty_obj);
GAPI_Assert(isRWOwn());
}
else if (isRWOwn())
{
util::get<rw_own_t>(m_ref) = {};
}
else GAPI_Assert(false); // shouldn't be called in *EXT modes
}
// Obtain a WRITE reference to underlying object
// Used by CPU kernel API wrappers when a kernel execution frame
// is created
T& wref()
{
GAPI_Assert(isRWExt() || isRWOwn());
if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
if (isRWOwn()) return util::get<rw_own_t>(m_ref);
util::throw_error(std::logic_error("Impossible happened"));
}
// Obtain a READ reference to underlying object
// Used by CPU kernel API wrappers when a kernel execution frame
// is created
const T& rref() const
{
// ANY object can be accessed for reading, even if it declared for
// output. Example -- a GComputation from [in] to [out1,out2]
// where [out2] is a result of operation applied to [out1]:
//
// GComputation boundary
// . . . . . . .
// . .
// [in] ----> foo() ----> [out1]
// . . :
// . . . .:. . .
// . V .
// . bar() ---> [out2]
// . . . . . . . . . . . .
//
if (isROExt()) return *util::get<ro_ext_t>(m_ref);
if (isRWExt()) return *util::get<rw_ext_t>(m_ref);
if (isRWOwn()) return util::get<rw_own_t>(m_ref);
util::throw_error(std::logic_error("Impossible happened"));
}
virtual void mov(BasicOpaqueRef &v) override {
OpaqueRefT<T> *tv = dynamic_cast<OpaqueRefT<T>*>(&v);
GAPI_Assert(tv != nullptr);
wref() = std::move(tv->wref());
}
virtual const void* ptr() const override { return &rref(); }
virtual void set(const cv::util::any &a) override {
wref() = util::any_cast<T>(a);
}
};
// This class strips type information from OpaqueRefT<> and makes it usable
// in the G-API executables (carrying run-time data/information to kernels).
// Part of GRunArg.
// Its methods are typed proxies to OpaqueRefT<T>.
// OpaqueRef maintains "reference" semantics so two copies of OpaqueRef refer
// to the same underlying object.
class OpaqueRef
{
std::shared_ptr<BasicOpaqueRef> m_ref;
cv::detail::OpaqueKind m_kind = cv::detail::OpaqueKind::CV_UNKNOWN;
template<typename T> inline void check() const
{
GAPI_DbgAssert(dynamic_cast<OpaqueRefT<T>*>(m_ref.get()) != nullptr);
}
public:
OpaqueRef() = default;
template<
typename T,
typename = util::are_different_t<OpaqueRef, T>
>
// FIXME: probably won't work with const object
explicit OpaqueRef(T&& obj) :
m_ref(new OpaqueRefT<util::decay_t<T>>(std::forward<T>(obj))),
m_kind(GOpaqueTraits<util::decay_t<T>>::kind) {}
cv::detail::OpaqueKind getKind() const
{
return m_kind;
}
template<typename T> void reset()
{
if (!m_ref) m_ref.reset(new OpaqueRefT<T>());
check<T>();
storeKind<T>();
static_cast<OpaqueRefT<T>&>(*m_ref).reset();
}
template <typename T>
void storeKind()
{
m_kind = cv::detail::GOpaqueTraits<T>::kind;
}
template<typename T> T& wref()
{
check<T>();
return static_cast<OpaqueRefT<T>&>(*m_ref).wref();
}
template<typename T> const T& rref() const
{
check<T>();
return static_cast<OpaqueRefT<T>&>(*m_ref).rref();
}
void mov(OpaqueRef &v)
{
m_ref->mov(*v.m_ref);
}
cv::GOpaqueDesc descr_of() const
{
return m_ref->m_desc;
}
// May be used to uniquely identify this object internally
const void *ptr() const { return m_ref->ptr(); }
// Introduced for in-graph meta handling
OpaqueRef& operator= (const cv::util::any &a)
{
m_ref->set(a);
return *this;
}
};
} // namespace detail
/** \addtogroup gapi_data_objects
* @{
*/
/**
* @brief `cv::GOpaque<T>` template class represents an object of
* class `T` in the graph.
*
* `cv::GOpaque<T>` describes a functional relationship between operations
* consuming and producing object of class `T`. `cv::GOpaque<T>` is
* designed to extend G-API with user-defined data types, which are
* often required with user-defined operations. G-API can't apply any
* optimizations to user-defined types since these types are opaque to
* the framework. However, there is a number of G-API operations
* declared with `cv::GOpaque<T>` as a return type,
* e.g. cv::gapi::streaming::timestamp() or cv::gapi::streaming::size().
*
* @sa `cv::GArray<T>`
*/
template<typename T> class GOpaque
{
public:
// Host type (or Flat type) - the type this GOpaque is actually
// specified to.
/// @private
using HT = typename detail::flatten_g<util::decay_t<T>>::type;
/**
* @brief Constructs an empty `cv::GOpaque<T>`
*
* Normally, empty G-API data objects denote a starting point of
* the graph. When an empty `cv::GOpaque<T>` is assigned to a result
* of some operation, it obtains a functional link to this
* operation (and is not empty anymore).
*/
GOpaque() { putDetails(); } // Empty constructor
/// @private
explicit GOpaque(detail::GOpaqueU &&ref) // GOpaqueU-based constructor
: m_ref(ref) { putDetails(); } // (used by GCall, not for users)
/// @private
detail::GOpaqueU strip() const {
return m_ref;
}
/// @private
static void Ctor(detail::OpaqueRef& ref) {
ref.reset<HT>();
}
private:
void putDetails() {
m_ref.setConstructFcn(&Ctor);
m_ref.specifyType<HT>();
m_ref.storeKind<HT>();
}
detail::GOpaqueU m_ref;
};
/** @} */
} // namespace cv
#endif // OPENCV_GAPI_GOPAQUE_HPP