src/api/gorigin.cpp
src/api/gmat.cpp
src/api/garray.cpp
+ src/api/gopaque.cpp
src/api/gscalar.cpp
src/api/gkernel.cpp
src/api/gbackend.cpp
{
return outVecRef(output).wref<T>();
}
+ template<typename T> T& outOpaqueR(int output) // FIXME: the same issue
+ {
+ return outOpaqueRef(output).wref<T>();
+ }
protected:
detail::VectorRef& outVecRef(int output);
+ detail::OpaqueRef& outOpaqueRef(int output);
std::vector<GArg> m_args;
{
static const std::vector<U>& get(GCPUContext &ctx, int idx) { return ctx.inArg<VectorRef>(idx).rref<U>(); }
};
+template<typename U> struct get_in<cv::GOpaque<U> >
+{
+ static const U& get(GCPUContext &ctx, int idx) { return ctx.inArg<OpaqueRef>(idx).rref<U>(); }
+};
//FIXME(dm): GArray<Mat>/GArray<GMat> conversion should be done more gracefully in the system
template<> struct get_in<cv::GArray<cv::GMat> >: public get_in<cv::GArray<cv::Mat> >
{
};
+//FIXME(dm): GArray<Scalar>/GArray<GScalar> conversion should be done more gracefully in the system
+template<> struct get_in<cv::GArray<cv::GScalar> >: public get_in<cv::GArray<cv::Scalar> >
+{
+};
+
+//FIXME(dm): GOpaque<Mat>/GOpaque<GMat> conversion should be done more gracefully in the system
+template<> struct get_in<cv::GOpaque<cv::GMat> >: public get_in<cv::GOpaque<cv::Mat> >
+{
+};
+
+//FIXME(dm): GOpaque<Scalar>/GOpaque<GScalar> conversion should be done more gracefully in the system
+template<> struct get_in<cv::GOpaque<cv::GScalar> >: public get_in<cv::GOpaque<cv::Mat> >
+{
+};
+
template<class T> struct get_in
{
static T get(GCPUContext &ctx, int idx) { return ctx.inArg<T>(idx); }
return ctx.outVecR<U>(idx);
}
};
+template<typename U> struct get_out<cv::GOpaque<U>>
+{
+ static U& get(GCPUContext &ctx, int idx)
+ {
+ return ctx.outOpaqueR<U>(idx);
+ }
+};
template<typename, typename, typename>
struct OCVCallHelper;
}
};
+template<typename U> struct fluid_get_in<cv::GOpaque<U>>
+{
+ static const U& get(const cv::GArgs &in_args, int idx)
+ {
+ return in_args.at(idx).unsafe_get<cv::detail::OpaqueRef>().rref<U>();
+ }
+};
+
template<class T> struct fluid_get_in
{
static const T& get(const cv::GArgs &in_args, int idx)
#include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/gscalar.hpp>
#include <opencv2/gapi/garray.hpp>
+#include <opencv2/gapi/gopaque.hpp>
#include <opencv2/gapi/gtype_traits.hpp>
#include <opencv2/gapi/gmetaarg.hpp>
#include <opencv2/gapi/own/scalar.hpp>
cv::gapi::wip::IStreamSource::Ptr,
cv::gapi::own::Mat,
cv::gapi::own::Scalar,
- cv::detail::VectorRef
+ cv::detail::VectorRef,
+ cv::detail::OpaqueRef
>;
using GRunArgs = std::vector<GRunArg>;
#endif // !defined(GAPI_STANDALONE)
cv::gapi::own::Mat*,
cv::gapi::own::Scalar*,
- cv::detail::VectorRef
+ cv::detail::VectorRef,
+ cv::detail::OpaqueRef
>;
using GRunArgsP = std::vector<GRunArgP>;
#include <opencv2/gapi/gmat.hpp> // GMat
#include <opencv2/gapi/gscalar.hpp> // GScalar
#include <opencv2/gapi/garray.hpp> // GArray<T>
+#include <opencv2/gapi/gopaque.hpp> // GOpaque<T>
namespace cv {
return GArray<T>(yieldArray(output));
}
+ template<class T> GOpaque<T> yieldOpaque(int output = 0)
+ {
+ return GOpaque<T>(yieldOpaque(output));
+ }
+
// Internal use only
Priv& priv();
const Priv& priv() const;
void setArgs(std::vector<GArg> &&args);
- // Public version returns a typed array, this one is implementation detail
+ // Public versions return a typed array or opaque, those are implementation details
detail::GArrayU yieldArray(int output = 0);
+ detail::GOpaqueU yieldOpaque(int output = 0);
};
} // namespace cv
GMAT,
GSCALAR,
GARRAY,
+ GOPAQUE,
};
struct GCompileArg;
}
};
+template<typename U> struct get_compound_in<cv::GOpaque<U>>
+{
+ static cv::GOpaque<U> get(GCompoundContext &ctx, int idx)
+ {
+ auto opaq = cv::GOpaque<U>();
+ ctx.m_args[idx] = GArg(opaq);
+ return opaq;
+ }
+};
+
template<typename, typename, typename>
struct GCompoundCallHelper;
{
static inline cv::GArray<U> yield(cv::GCall &call, int i) { return call.yieldArray<U>(i); }
};
+ template<typename U> struct Yield<cv::GOpaque<U> >
+ {
+ static inline cv::GOpaque<U> yield(cv::GCall &call, int i) { return call.yieldOpaque<U>(i); }
+ };
} // anonymous namespace
////////////////////////////////////////////////////////////////////////////
template<> struct MetaType<cv::GMat> { using type = GMatDesc; };
template<> struct MetaType<cv::GMatP> { using type = GMatDesc; };
template<> struct MetaType<cv::GScalar> { using type = GScalarDesc; };
- template<typename U> struct MetaType<cv::GArray<U> > { using type = GArrayDesc; };
+ template<typename U> struct MetaType<cv::GArray<U> > { using type = GArrayDesc; };
+ template<typename U> struct MetaType<cv::GOpaque<U> > { using type = GOpaqueDesc; };
template<typename T> struct MetaType { using type = T; }; // opaque args passed as-is
// 2. Hacky test based on MetaType to check if we operate on G-* type or not
* cv::GMat | cv::Mat
* cv::GScalar | cv::Scalar
* `cv::GArray<T>` | std::vector<T>
+ * `cv::GOpaque<T>` | T
*/
class GAPI_EXPORTS GMat
{
#include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/gscalar.hpp>
#include <opencv2/gapi/garray.hpp>
+#include <opencv2/gapi/gopaque.hpp>
namespace cv
{
, GMatDesc
, GScalarDesc
, GArrayDesc
+ , GOpaqueDesc
>;
GAPI_EXPORTS std::ostream& operator<<(std::ostream& os, const GMetaArg &);
template<> struct is_meta_descr<GMatDesc> : std::true_type {};
template<> struct is_meta_descr<GScalarDesc> : std::true_type {};
template<> struct is_meta_descr<GArrayDesc> : std::true_type {};
+ template<> struct is_meta_descr<GOpaqueDesc> : std::true_type {};
template<typename... Ts>
using are_meta_descrs = all_satisfy<is_meta_descr, Ts...>;
--- /dev/null
+// 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 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/variant.hpp>
+#include <opencv2/gapi/util/throw.hpp>
+#include <opencv2/gapi/own/assert.hpp>
+
+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 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 {};}
+static 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>
+
+ 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 = typename std::decay<T>::type;
+ return dynamic_cast<TypeHint<U>*>(m_hint.get()) != nullptr;
+ };
+
+ template <typename T>
+ void GOpaqueU::specifyType(){
+ m_hint.reset(new TypeHint<typename std::decay<T>::type>);
+ };
+
+ // 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;
+ };
+
+ 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());
+ }
+ };
+
+ // 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;
+
+ template<typename T> inline void check() const
+ {
+ GAPI_DbgAssert(dynamic_cast<OpaqueRefT<T>*>(m_ref.get()) != nullptr);
+ }
+
+ public:
+ OpaqueRef() = default;
+
+ template<typename T> explicit OpaqueRef(T&& obj) :
+ m_ref(new OpaqueRefT<typename std::decay<T>::type>(std::forward<T>(obj))) {}
+
+ template<typename T> void reset()
+ {
+ if (!m_ref) m_ref.reset(new OpaqueRefT<T>());
+
+ check<T>();
+ static_cast<OpaqueRefT<T>&>(*m_ref).reset();
+ }
+
+ 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;
+ }
+ };
+} // namespace detail
+
+/** \addtogroup gapi_data_objects
+ * @{
+ */
+
+template<typename T> class GOpaque
+{
+public:
+ GOpaque() { putDetails(); } // Empty constructor
+ explicit GOpaque(detail::GOpaqueU &&ref) // GOpaqueU-based constructor
+ : m_ref(ref) { putDetails(); } // (used by GCall, not for users)
+
+ detail::GOpaqueU strip() const { return m_ref; }
+
+private:
+ // Host type (or Flat type) - the type this GOpaque is actually
+ // specified to.
+ using HT = typename detail::flatten_g<typename std::decay<T>::type>::type;
+
+ static void CTor(detail::OpaqueRef& ref) {
+ ref.reset<HT>();
+ }
+ void putDetails() {
+ m_ref.setConstructFcn(&CTor);
+ m_ref.specifyType<HT>();
+ }
+
+ detail::GOpaqueU m_ref;
+};
+
+/** @} */
+
+} // namespace cv
+
+#endif // OPENCV_GAPI_GOPAQUE_HPP
#include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/gscalar.hpp>
#include <opencv2/gapi/garray.hpp>
+#include <opencv2/gapi/gopaque.hpp>
#include <opencv2/gapi/garg.hpp>
#include <opencv2/gapi/gmetaarg.hpp>
< GMat
, GMatP
, GScalar
- , detail::GArrayU // instead of GArray<T>
+ , detail::GArrayU // instead of GArray<T>
+ , detail::GOpaqueU // instead of GOpaque<T>
>;
using GProtoArgs = std::vector<GProtoArg>;
#include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/gscalar.hpp>
#include <opencv2/gapi/garray.hpp>
+#include <opencv2/gapi/gopaque.hpp>
#include <opencv2/gapi/streaming/source.hpp>
#include <opencv2/gapi/gcommon.hpp>
#include <opencv2/gapi/own/convert.hpp>
GMAT, // a cv::GMat
GMATP, // a cv::GMatP
GSCALAR, // a cv::GScalar
- GARRAY, // a cv::GArrayU (note - exactly GArrayU, not GArray<T>!)
+ GARRAY, // a cv::GArrayU (note - exactly GArrayU, not GArray<T>!)
+ GOPAQUE, // a cv::GOpaqueU (note - exactly GOpaqueU, not GOpaque<T>!)
};
// Describe G-API types (G-types) with traits. Mostly used by
static cv::detail::VectorRef wrap_in (const std::vector<T> &t) { return detail::VectorRef(t); }
static cv::detail::VectorRef wrap_out ( std::vector<T> &t) { return detail::VectorRef(t); }
};
+ template<class T> struct GTypeTraits<cv::GOpaque<T> >
+ {
+ static constexpr const ArgKind kind = ArgKind::GOPAQUE;
+ static constexpr const GShape shape = GShape::GOPAQUE;
+ using host_type = T;
+ using strip_type = cv::detail::OpaqueRef;
+ static cv::detail::GOpaqueU wrap_value(const cv::GOpaque<T> &t) { return t.strip();}
+ static cv::detail::OpaqueRef wrap_in (const T &t) { return detail::OpaqueRef(t); }
+ static cv::detail::OpaqueRef wrap_out ( T &t) { return detail::OpaqueRef(t); }
+ };
// Tests if Trait for type T requires extra marshalling ("custom wrap") or not.
// If Traits<T> has wrap_value() defined, it does.
template<> struct GTypeOf<cv::gapi::own::Mat> { using type = cv::GMat; };
template<> struct GTypeOf<cv::gapi::own::Scalar> { using type = cv::GScalar; };
template<typename U> struct GTypeOf<std::vector<U> > { using type = cv::GArray<U>; };
+ template<typename U> struct GTypeOf { using type = cv::GOpaque<U>;};
// FIXME: This is not quite correct since IStreamSource may produce not only Mat but also Scalar
// and vector data. TODO: Extend the type dispatching on these types too.
template<> struct GTypeOf<cv::gapi::wip::IStreamSource::Ptr> { using type = cv::GMat;};
template<typename T> using wrap_gapi_helper = WrapValue<typename std::decay<T>::type>;
template<typename T> using wrap_host_helper = WrapValue<typename std::decay<g_type_of_t<T> >::type>;
-
} // namespace detail
} // namespace cv
template<typename T> struct ProtoToParam;
template<> struct ProtoToParam<cv::GMat> { using type = cv::Mat; };
template<> struct ProtoToParam<cv::GScalar> { using type = cv::Scalar; };
- template<typename U> struct ProtoToParam<cv::GArray<U> > { using type = std::vector<U>; };
+ template<typename U> struct ProtoToParam<cv::GArray<U> > { using type = std::vector<U>; };
+ template<typename U> struct ProtoToParam<cv::GOpaque<U> > { using type = U; };
template<typename T> using ProtoToParamT = typename ProtoToParam<T>::type;
template<typename T> struct ProtoToMeta;
template<> struct ProtoToMeta<cv::GMat> { using type = cv::GMatDesc; };
template<> struct ProtoToMeta<cv::GScalar> { using type = cv::GScalarDesc; };
- template<typename U> struct ProtoToMeta<cv::GArray<U> > { using type = cv::GArrayDesc; };
+ template<typename U> struct ProtoToMeta<cv::GArray<U> > { using type = cv::GArrayDesc; };
+ template<typename U> struct ProtoToMeta<cv::GOpaque<U> > { using type = cv::GOpaqueDesc; };
template<typename T> using ProtoToMetaT = typename ProtoToMeta<T>::type;
//workaround for MSVC 19.0 bug
{
return outVecRef(output).wref<T>();
}
+ template<typename T> T& outOpaqueR(int output) // FIXME: the same issue
+ {
+ return outOpaqueRef(output).wref<T>();
+ }
protected:
detail::VectorRef& outVecRef(int output);
+ detail::VectorRef& outOpaqueRef(int output);
std::vector<GArg> m_args;
std::unordered_map<std::size_t, GRunArgP> m_results;
{
static const std::vector<U>& get(GOCLContext &ctx, int idx) { return ctx.inArg<VectorRef>(idx).rref<U>(); }
};
+template<typename U> struct ocl_get_in<cv::GOpaque<U> >
+{
+ static const U& get(GOCLContext &ctx, int idx) { return ctx.inArg<OpaqueRef>(idx).rref<U>(); }
+};
template<class T> struct ocl_get_in
{
static T get(GOCLContext &ctx, int idx) { return ctx.inArg<T>(idx); }
{
static std::vector<U>& get(GOCLContext &ctx, int idx) { return ctx.outVecR<U>(idx); }
};
+template<typename U> struct ocl_get_out<cv::GOpaque<U> >
+{
+ static U& get(GOCLContext &ctx, int idx) { return ctx.outOpaqueR<U>(idx); }
+};
template<typename, typename, typename>
struct OCLCallHelper;
mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg);
break;
+ case GShape::GOPAQUE:
+ mag.template slot<cv::detail::OpaqueRef>()[rc.id] = util::get<cv::detail::OpaqueRef>(arg);
+ break;
+
default:
util::throw_error(std::logic_error("Unsupported GShape type"));
}
mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg);
break;
+ case GShape::GOPAQUE:
+ mag.template slot<cv::detail::OpaqueRef>()[rc.id] = util::get<cv::detail::OpaqueRef>(arg);
+ break;
+
default:
util::throw_error(std::logic_error("Unsupported GShape type"));
break;
(mag.template slot<cv::detail::VectorRef>()[d.rc]);
break;
+ case GShape::GOPAQUE:
+ util::get<cv::detail::ConstructOpaque>(d.ctor)
+ (mag.template slot<cv::detail::OpaqueRef>()[d.rc]);
+ break;
+
case GShape::GSCALAR:
mag.template slot<cv::gapi::own::Scalar>()[d.rc] = cv::gapi::own::Scalar();
break;
{
case GShape::GMAT: return GRunArg(mag.template slot<cv::gapi::own::Mat>().at(ref.id));
case GShape::GSCALAR: return GRunArg(mag.template slot<cv::gapi::own::Scalar>().at(ref.id));
- // Note: .at() is intentional for GArray as object MUST be already there
+ // Note: .at() is intentional for GArray and GOpaque as objects MUST be already there
// (and constructed by either bindIn/Out or resetInternal)
case GShape::GARRAY: return GRunArg(mag.template slot<cv::detail::VectorRef>().at(ref.id));
+ case GShape::GOPAQUE: return GRunArg(mag.template slot<cv::detail::OpaqueRef>().at(ref.id));
default:
util::throw_error(std::logic_error("Unsupported GShape type"));
break;
else
return GRunArgP(&mag.template slot<cv::gapi::own::Mat>()[rc.id]);
case GShape::GSCALAR: return GRunArgP(&mag.template slot<cv::gapi::own::Scalar>()[rc.id]);
- // Note: .at() is intentional for GArray as object MUST be already there
+ // Note: .at() is intentional for GArray and GOpaque as objects MUST be already there
// (and constructor by either bindIn/Out or resetInternal)
case GShape::GARRAY:
// FIXME(DM): For some absolutely unknown to me reason, move
// debugging this!!!1
return GRunArgP(const_cast<const Mag&>(mag)
.template slot<cv::detail::VectorRef>().at(rc.id));
+ case GShape::GOPAQUE:
+ // FIXME(DM): For some absolutely unknown to me reason, move
+ // semantics is involved here without const_cast to const (and
+ // value from map is moved into return value GRunArgP, leaving
+ // map with broken value I've spent few late Friday hours
+ // debugging this!!!1
+ return GRunArgP(const_cast<const Mag&>(mag)
+ .template slot<cv::detail::OpaqueRef>().at(rc.id));
default:
util::throw_error(std::logic_error("Unsupported GShape type"));
break;
case GShape::GARRAY:
// Do nothing - should we really do anything here?
break;
+ case GShape::GOPAQUE:
+ // Do nothing - should we really do anything here?
+ break;
case GShape::GMAT:
{
return cv::detail::GArrayU(m_priv->m_node, output);
}
+cv::detail::GOpaqueU cv::GCall::yieldOpaque(int output)
+{
+ return cv::detail::GOpaqueU(m_priv->m_node, output);
+}
+
cv::GCall::Priv& cv::GCall::priv()
{
return *m_priv;
--- /dev/null
+// 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 Intel Corporation
+
+
+#include "precomp.hpp"
+#include <opencv2/gapi/gopaque.hpp>
+#include "api/gorigin.hpp"
+
+// cv::detail::GOpaqueU public implementation ///////////////////////////////////
+cv::detail::GOpaqueU::GOpaqueU()
+ : m_priv(new GOrigin(GShape::GOPAQUE, cv::GNode::Param()))
+{
+}
+
+cv::detail::GOpaqueU::GOpaqueU(const GNode &n, std::size_t out)
+ : m_priv(new GOrigin(GShape::GOPAQUE, n, out))
+{
+}
+
+cv::GOrigin& cv::detail::GOpaqueU::priv()
+{
+ return *m_priv;
+}
+
+const cv::GOrigin& cv::detail::GOpaqueU::priv() const
+{
+ return *m_priv;
+}
+
+void cv::detail::GOpaqueU::setConstructFcn(ConstructOpaque &&co)
+{
+ m_priv->ctor = std::move(co);
+}
+
+namespace cv {
+std::ostream& operator<<(std::ostream& os, const cv::GOpaqueDesc &)
+{
+ // FIXME: add type information here
+ os << "(Opaque)";
+ return os;
+}
+}
case cv::GProtoArg::index_of<cv::detail::GArrayU>():
return util::get<cv::detail::GArrayU>(arg).priv();
+ case cv::GProtoArg::index_of<cv::detail::GOpaqueU>():
+ return util::get<cv::detail::GOpaqueU>(arg).priv();
+
default:
util::throw_error(std::logic_error("Unsupported GProtoArg type"));
}
case detail::ArgKind::GMATP:
case detail::ArgKind::GSCALAR:
case detail::ArgKind::GARRAY:
+ case detail::ArgKind::GOPAQUE:
return true;
default:
case detail::ArgKind::GMATP: return GProtoArg(arg.get<cv::GMatP>());
case detail::ArgKind::GSCALAR: return GProtoArg(arg.get<cv::GScalar>());
case detail::ArgKind::GARRAY: return GProtoArg(arg.get<cv::detail::GArrayU>());
+ case detail::ArgKind::GOPAQUE: return GProtoArg(arg.get<cv::detail::GOpaqueU>());
default: util::throw_error(std::logic_error("Unsupported GArg type"));
}
}
case GRunArg::index_of<cv::detail::VectorRef>():
return cv::GMetaArg(util::get<cv::detail::VectorRef>(arg).descr_of());
+ case GRunArg::index_of<cv::detail::OpaqueRef>():
+ return cv::GMetaArg(util::get<cv::detail::OpaqueRef>(arg).descr_of());
+
case GRunArg::index_of<cv::gapi::wip::IStreamSource::Ptr>():
return cv::util::get<cv::gapi::wip::IStreamSource::Ptr>(arg)->descr_of();
case GRunArgP::index_of<cv::gapi::own::Mat*>(): return GMetaArg(descr_of(*util::get<cv::gapi::own::Mat*>(argp)));
case GRunArgP::index_of<cv::gapi::own::Scalar*>(): return GMetaArg(descr_of(*util::get<cv::gapi::own::Scalar*>(argp)));
case GRunArgP::index_of<cv::detail::VectorRef>(): return GMetaArg(util::get<cv::detail::VectorRef>(argp).descr_of());
+ case GRunArgP::index_of<cv::detail::OpaqueRef>(): return GMetaArg(util::get<cv::detail::OpaqueRef>(argp).descr_of());
default: util::throw_error(std::logic_error("Unsupported GRunArgP type"));
}
}
util::get<GMatDesc>(meta).canDescribe(*util::get<cv::gapi::own::Mat*>(argp));
case GRunArgP::index_of<cv::gapi::own::Scalar*>(): return meta == GMetaArg(descr_of(*util::get<cv::gapi::own::Scalar*>(argp)));
case GRunArgP::index_of<cv::detail::VectorRef>(): return meta == GMetaArg(util::get<cv::detail::VectorRef>(argp).descr_of());
+ case GRunArgP::index_of<cv::detail::OpaqueRef>(): return meta == GMetaArg(util::get<cv::detail::OpaqueRef>(argp).descr_of());
default: util::throw_error(std::logic_error("Unsupported GRunArgP type"));
}
}
util::get<GMatDesc>(meta).canDescribe(util::get<cv::gapi::own::Mat>(arg));
case GRunArg::index_of<cv::gapi::own::Scalar>(): return meta == cv::GMetaArg(descr_of(util::get<cv::gapi::own::Scalar>(arg)));
case GRunArg::index_of<cv::detail::VectorRef>(): return meta == cv::GMetaArg(util::get<cv::detail::VectorRef>(arg).descr_of());
+ case GRunArg::index_of<cv::detail::OpaqueRef>(): return meta == cv::GMetaArg(util::get<cv::detail::OpaqueRef>(arg).descr_of());
case GRunArg::index_of<cv::gapi::wip::IStreamSource::Ptr>(): return util::holds_alternative<GMatDesc>(meta); // FIXME(?) may be not the best option
default: util::throw_error(std::logic_error("Unsupported GRunArg type"));
}
case cv::GMetaArg::index_of<cv::GArrayDesc>():
os << util::get<cv::GArrayDesc>(arg);
break;
+
+ case cv::GMetaArg::index_of<cv::GOpaqueDesc>():
+ os << util::get<cv::GOpaqueDesc>(arg);
+ break;
default:
GAPI_Assert(false);
}
} // namespace magazine
#if !defined(GAPI_STANDALONE)
-using Mag = magazine::Class<cv::gapi::own::Mat, cv::UMat, cv::gapi::own::Scalar, cv::detail::VectorRef>;
+using Mag = magazine::Class<cv::gapi::own::Mat, cv::UMat, cv::gapi::own::Scalar, cv::detail::VectorRef, cv::detail::OpaqueRef>;
#else
-using Mag = magazine::Class<cv::gapi::own::Mat, cv::gapi::own::Scalar, cv::detail::VectorRef>;
+using Mag = magazine::Class<cv::gapi::own::Mat, cv::gapi::own::Scalar, cv::detail::VectorRef, cv::detail::OpaqueRef>;
#endif
namespace magazine
// FIXME: this check has to be done somewhere in compilation stage.
GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT
&& arg.kind != cv::detail::ArgKind::GSCALAR
- && arg.kind != cv::detail::ArgKind::GARRAY);
+ && arg.kind != cv::detail::ArgKind::GARRAY
+ && arg.kind != cv::detail::ArgKind::GOPAQUE);
if (arg.kind != cv::detail::ArgKind::GOBJREF)
{
{
case GShape::GMAT: return GArg(m_res.slot<cv::gapi::own::Mat>() [ref.id]);
case GShape::GSCALAR: return GArg(m_res.slot<cv::gapi::own::Scalar>()[ref.id]);
- // Note: .at() is intentional for GArray as object MUST be already there
+ // Note: .at() is intentional for GArray and GOpaque as objects MUST be already there
// (and constructed by either bindIn/Out or resetInternal)
case GShape::GARRAY: return GArg(m_res.slot<cv::detail::VectorRef>().at(ref.id));
+ case GShape::GOPAQUE: return GArg(m_res.slot<cv::detail::OpaqueRef>().at(ref.id));
default:
util::throw_error(std::logic_error("Unsupported GShape type"));
break;
return util::get<cv::detail::VectorRef>(m_results.at(output));
}
+cv::detail::OpaqueRef& cv::GCPUContext::outOpaqueRef(int output)
+{
+ return util::get<cv::detail::OpaqueRef>(m_results.at(output));
+}
+
cv::GCPUKernel::GCPUKernel()
{
}
case GShape::GMAT: m_buffers[m_id_map.at(rc.id)].priv().bindTo(util::get<cv::gapi::own::Mat>(arg), true); break;
case GShape::GSCALAR: m_res.slot<cv::gapi::own::Scalar>()[rc.id] = util::get<cv::gapi::own::Scalar>(arg); break;
case GShape::GARRAY: m_res.slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg); break;
+ case GShape::GOPAQUE: m_res.slot<cv::detail::OpaqueRef>()[rc.id] = util::get<cv::detail::OpaqueRef>(arg); break;
}
}
{
GAPI_Assert(op_arg.kind != cv::detail::ArgKind::GMAT
&& op_arg.kind != cv::detail::ArgKind::GSCALAR
- && op_arg.kind != cv::detail::ArgKind::GARRAY);
+ && op_arg.kind != cv::detail::ArgKind::GARRAY
+ && op_arg.kind != cv::detail::ArgKind::GOPAQUE);
if (op_arg.kind == cv::detail::ArgKind::GOBJREF)
{
{
in_arg = GArg(m_res.slot<cv::detail::VectorRef>()[ref.id]);
}
+ else if (ref.shape == GShape::GOPAQUE)
+ {
+ in_arg = GArg(m_res.slot<cv::detail::OpaqueRef>()[ref.id]);
+ }
}
}
std::vector<FluidAgent*> m_script;
- using Magazine = detail::magazine<cv::gapi::own::Scalar, cv::detail::VectorRef>;
+ using Magazine = detail::magazine<cv::gapi::own::Scalar, cv::detail::VectorRef, cv::detail::OpaqueRef>;
Magazine m_res;
std::size_t m_num_int_buffers; // internal buffers counter (m_buffers - num_scratch)
#include <opencv2/gapi/gcommon.hpp>
#include <opencv2/gapi/garray.hpp>
+#include <opencv2/gapi/gopaque.hpp>
#include <opencv2/gapi/util/any.hpp>
#include <opencv2/gapi/gtype_traits.hpp>
#include <opencv2/gapi/infer.hpp>
// (and constructed by either bindIn/Out or resetInternal)
case GShape::GARRAY: return GArg(m_res.slot<cv::detail::VectorRef>().at(ref.id));
+ // Note: .at() is intentional for GOpaque as object MUST be already there
+ // (and constructed by either bindIn/Out or resetInternal)
+ case GShape::GOPAQUE: return GArg(m_res.slot<cv::detail::OpaqueRef>().at(ref.id));
+
default:
util::throw_error(std::logic_error("Unsupported GShape type"));
break;
// FIXME: this check has to be done somewhere in compilation stage.
GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT
&& arg.kind != cv::detail::ArgKind::GSCALAR
- && arg.kind != cv::detail::ArgKind::GARRAY);
+ && arg.kind != cv::detail::ArgKind::GARRAY
+ && arg.kind != cv::detail::ArgKind::GOPAQUE);
if (arg.kind != cv::detail::ArgKind::GOBJREF)
{
{
case GShape::GMAT: return GArg(m_res.slot<cv::UMat>()[ref.id]);
case GShape::GSCALAR: return GArg(m_res.slot<cv::gapi::own::Scalar>()[ref.id]);
- // Note: .at() is intentional for GArray as object MUST be already there
+ // Note: .at() is intentional for GArray as object MUST be already there
// (and constructed by either bindIn/Out or resetInternal)
case GShape::GARRAY: return GArg(m_res.slot<cv::detail::VectorRef>().at(ref.id));
+ // Note: .at() is intentional for GOpaque as object MUST be already there
+ // (and constructed by either bindIn/Out or resetInternal)
+ case GShape::GOPAQUE: return GArg(m_res.slot<cv::detail::OpaqueRef>().at(ref.id));
default:
util::throw_error(std::logic_error("Unsupported GShape type"));
break;
{
GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT
&& arg.kind != cv::detail::ArgKind::GSCALAR
- && arg.kind != cv::detail::ArgKind::GARRAY);
+ && arg.kind != cv::detail::ArgKind::GARRAY
+ && arg.kind != cv::detail::ArgKind::GOPAQUE);
if (arg.kind != cv::detail::ArgKind::GOBJREF)
{
case GProtoArg::index_of<cv::detail::GArrayU>():
return util::holds_alternative<cv::GArrayDesc>(meta);
+ case GProtoArg::index_of<cv::detail::GOpaqueU>():
+ return util::holds_alternative<cv::GOpaqueDesc>(meta);
+
default:
GAPI_Assert(false);
}
namespace gimpl
{
- // Union type for various user-defined type constructors (GArray<T>, etc)
+ // Union type for various user-defined type constructors (GArray<T>, GOpaque<T>, etc)
// FIXME: Replace construct-only API with a more generic one
// (probably with bits of introspection)
// Not required for non-user-defined types (GMat, GScalar, etc)
using HostCtor = util::variant
< util::monostate
, detail::ConstructVec
+ , detail::ConstructOpaque
>;
using ConstVal = util::variant
{cv::GShape::GMAT, "GMat"},
{cv::GShape::GSCALAR, "GScalar"},
{cv::GShape::GARRAY, "GArray"},
+ {cv::GShape::GOPAQUE, "GOpaque"},
};
auto format_op_label = [&gr](ade::NodeHandle nh) -> std::string {
--- /dev/null
+// 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 Intel Corporation
+
+#include "test_precomp.hpp"
+#include <string>
+#include <utility>
+
+namespace opencv_test
+{
+
+namespace ThisTest
+{
+using GPointOpaque = cv::GOpaque<cv::Point>;
+
+G_TYPED_KERNEL(GeneratePoint, <GPointOpaque(GMat)>, "test.opaque.gen_point")
+{
+ static GOpaqueDesc outMeta(const GMatDesc&) { return empty_gopaque_desc(); }
+};
+
+G_TYPED_KERNEL(FillMat, <GMat(cv::GOpaque<int>, int, int, cv::Size)>, "test.opaque.fill_mat")
+{
+ static GMatDesc outMeta(const GOpaqueDesc&, int depth, int chan, cv::Size size)
+ {
+ return cv::GMatDesc{depth, chan, size};
+ }
+};
+
+G_TYPED_KERNEL(PaintPoint, <GMat(GPointOpaque, int, int, cv::Size)>, "test.opaque.paint_point")
+{
+ static GMatDesc outMeta(const GOpaqueDesc&, int depth, int chan, cv::Size size)
+ {
+ return cv::GMatDesc{depth, chan, size};
+ }
+};
+
+struct MyCustomType{
+ int num;
+ std::string s;
+};
+
+using GOpaq2 = std::tuple<GOpaque<MyCustomType>,GOpaque<MyCustomType>>;
+
+G_TYPED_KERNEL_M(GenerateOpaque, <GOpaq2(GMat, GMat, std::string)>, "test.opaque.gen_point_multy")
+{
+ static std::tuple<GOpaqueDesc, GOpaqueDesc> outMeta(const GMatDesc&, const GMatDesc&, std::string)
+ {
+ return std::make_tuple(empty_gopaque_desc(), empty_gopaque_desc());
+ }
+};
+
+} // namespace ThisTest
+
+namespace
+{
+GAPI_OCV_KERNEL(OCVGeneratePoint, ThisTest::GeneratePoint)
+{
+ static void run(const cv::Mat&, cv::Point& out)
+ {
+ out = cv::Point(42, 42);
+ }
+};
+
+GAPI_OCV_KERNEL(OCVFillMat, ThisTest::FillMat)
+{
+ static void run(int a, int, int, cv::Size, cv::Mat& out)
+ {
+ out = cv::Scalar(a);
+ }
+};
+
+GAPI_OCV_KERNEL(OCVPaintPoint, ThisTest::PaintPoint)
+{
+ static void run(cv::Point a, int, int, cv::Size, cv::Mat& out)
+ {
+ out.at<uint8_t>(a) = 77;
+ }
+};
+
+GAPI_OCV_KERNEL(OCVGenerateOpaque, ThisTest::GenerateOpaque)
+{
+ static void run(const cv::Mat& a, const cv::Mat& b, const std::string& s,
+ ThisTest::MyCustomType &out1, ThisTest::MyCustomType &out2)
+ {
+ out1.num = a.size().width * a.size().height;
+ out1.s = s;
+
+ out2.num = b.size().width * b.size().height;
+ auto s2 = s;
+ std::reverse(s2.begin(), s2.end());
+ out2.s = s2;
+ }
+};
+} // (anonymous namespace)
+
+TEST(GOpaque, TestOpaqueOut)
+{
+ cv::Mat input = cv::Mat(52, 52, CV_8U);
+ cv::Point point;
+
+ cv::GMat in;
+ auto out = ThisTest::GeneratePoint::on(in);
+
+ cv::GComputation c(cv::GIn(in), cv::GOut(out));
+ c.apply(cv::gin(input), cv::gout(point), cv::compile_args(cv::gapi::kernels<OCVGeneratePoint>()));
+
+ EXPECT_TRUE(point == cv::Point(42, 42));
+}
+
+TEST(GOpaque, TestOpaqueIn)
+{
+ cv::Size sz = {42, 42};
+ int depth = CV_8U;
+ int chan = 1;
+ cv::Mat mat = cv::Mat(sz, CV_MAKETYPE(depth, chan));
+ int fill = 0;
+
+ cv::GOpaque<int> in;
+ auto out = ThisTest::FillMat::on(in, depth, chan, sz);
+
+ cv::GComputation c(cv::GIn(in), cv::GOut(out));
+ c.apply(cv::gin(fill), cv::gout(mat), cv::compile_args(cv::gapi::kernels<OCVFillMat>()));
+
+ auto diff = cv::Mat(sz, CV_MAKETYPE(depth, chan), cv::Scalar(fill)) - mat;
+ EXPECT_EQ(cv::countNonZero(diff), 0);
+}
+
+TEST(GOpaque, TestOpaqueBetween)
+{
+ cv::Size sz = {50, 50};
+ int depth = CV_8U;
+ int chan = 1;
+ cv::Mat mat_in = cv::Mat::zeros(sz, CV_MAKETYPE(depth, chan));
+ cv::Mat mat_out = cv::Mat::zeros(sz, CV_MAKETYPE(depth, chan));
+
+ cv::GMat in, out;
+ auto betw = ThisTest::GeneratePoint::on(in);
+ out = ThisTest::PaintPoint::on(betw, depth, chan, sz);
+
+ cv::GComputation c(cv::GIn(in), cv::GOut(out));
+ c.apply(cv::gin(mat_in), cv::gout(mat_out), cv::compile_args(cv::gapi::kernels<OCVGeneratePoint, OCVPaintPoint>()));
+
+ int painted = mat_out.at<uint8_t>(42, 42);
+ EXPECT_EQ(painted, 77);
+}
+
+TEST(GOpaque, TestOpaqueCustomOut2)
+{
+ cv::Mat input1 = cv::Mat(52, 52, CV_8U);
+ cv::Mat input2 = cv::Mat(42, 42, CV_8U);
+ std::string str = "opaque";
+ std::string str2 = str;
+ std::reverse(str2.begin(), str2.end());
+
+ ThisTest::MyCustomType out1, out2;
+
+ cv::GMat in1, in2;
+ auto out = ThisTest::GenerateOpaque::on(in1, in2, str);
+
+ cv::GComputation c(cv::GIn(in1, in2), cv::GOut(std::get<0>(out), std::get<1>(out)));
+ c.apply(cv::gin(input1, input2), cv::gout(out1, out2), cv::compile_args(cv::gapi::kernels<OCVGenerateOpaque>()));
+
+ EXPECT_EQ(out1.num, input1.size().width * input1.size().height);
+ EXPECT_EQ(out1.s, str);
+
+ EXPECT_EQ(out2.num, input2.size().width * input2.size().height);
+ EXPECT_EQ(out2.s, str2);
+}
+
+TEST(GOpaque_OpaqueRef, TestMov)
+{
+ // Warning: this test is testing some not-very-public APIs
+ // Test how OpaqueRef's mov() (aka poor man's move()) is working.
+
+ using I = std::string;
+
+ std::string str = "this string must be long due to short string optimization";
+ const I gold(str);
+
+ I test = gold;
+ const char* ptr = test.data();
+
+ cv::detail::OpaqueRef ref(test);
+ cv::detail::OpaqueRef mov;
+ mov.reset<I>();
+
+ EXPECT_EQ(gold, ref.rref<I>()); // ref = gold
+
+ mov.mov(ref);
+ EXPECT_EQ(gold, mov.rref<I>()); // mov obtained the data
+ EXPECT_EQ(ptr, mov.rref<I>().data()); // pointer is unchanged (same data)
+ EXPECT_EQ(test, ref.rref<I>()); // ref = test
+ EXPECT_NE(test, mov.rref<I>()); // ref lost the data
+}
+} // namespace opencv_test
using GMat3 = std::tuple<GMat, GMat, GMat>;
using GScalar = cv::GScalar;
template <typename T> using GArray = cv::GArray<T>;
+template <typename T> using GOpaque = cv::GOpaque<T>;
using ArrayT = int;
using WrongArrayT = char;
+struct CustomType{
+ cv::Mat mat;
+ int i;
+ void *v;
+ CustomType* next;
+};
+
+struct AnotherCustomType{
+ cv::Mat mat;
+ int i;
+ void *v;
+};
+
+using OpaqueT = CustomType;
+using WrongOpaqueT = AnotherCustomType;
+
GAPI_TRANSFORM(gmat_in_gmat_out, <GMat(GMat)>, "gmat_in_gmat_out")
{
static GMat pattern(GMat) { return {}; }
static GMat2 substitute(GMat, GScalar, GArray<ArrayT>) { return {}; }
};
+GAPI_TRANSFORM(gop_in_gmat_out, <GMat(GOpaque<OpaqueT>)>, "gop_in_gmat_out")
+{
+ static GMat pattern(GOpaque<OpaqueT>) { return {}; }
+ static GMat substitute(GOpaque<OpaqueT>) { return {}; }
+};
+
+GAPI_TRANSFORM(gmat_in_gop_out, <GOpaque<OpaqueT>(GMat)>, "gmat_in_gop_out")
+{
+ static GOpaque<OpaqueT> pattern(GMat) { return {}; }
+ static GOpaque<OpaqueT> substitute(GMat) { return {}; }
+};
+
+GAPI_TRANSFORM(gop_in_gscalar_out, <GScalar(GOpaque<OpaqueT>)>, "gop_in_gscalar_out")
+{
+ static GScalar pattern(GOpaque<OpaqueT>) { return {}; }
+ static GScalar substitute(GOpaque<OpaqueT>) { return {}; }
+};
+
+GAPI_TRANSFORM(gscalar_in_gop_out, <GOpaque<OpaqueT>(GScalar)>, "gscalar_in_gop_out")
+{
+ static GOpaque<OpaqueT> pattern(GScalar) { return {}; }
+ static GOpaque<OpaqueT> substitute(GScalar) { return {}; }
+};
+
+GAPI_TRANSFORM(gmat_gsc_gopaque_in_gmat2_out, <GMat2(GMat, GScalar, GOpaque<OpaqueT>)>, "gmat_gsc_gopaque_in_gmat2_out")
+{
+ static GMat2 pattern(GMat, GScalar, GOpaque<OpaqueT>) { return {}; }
+ static GMat2 substitute(GMat, GScalar, GOpaque<OpaqueT>) { return {}; }
+};
+
} // anonymous namespace
TEST(KernelPackageTransform, CreatePackage)
, garr_in_gscalar_out
, gscalar_in_garr_out
, gmat_gsc_garray_in_gmat2_out
+ , gop_in_gmat_out
+ , gmat_in_gop_out
+ , gop_in_gscalar_out
+ , gscalar_in_gop_out
+ , gmat_gsc_gopaque_in_gmat2_out
>();
auto tr = pkg.get_transformations();
- EXPECT_EQ(11u, tr.size());
+ EXPECT_EQ(16u, tr.size());
}
TEST(KernelPackageTransform, Include)
check(tr.substitute());
}
+TEST(KernelPackageTransform, gmat_gsc_gopaque_in_gmat2_out)
+{
+ auto tr = gmat_gsc_gopaque_in_gmat2_out::transformation();
+
+ auto check = [](const cv::GComputation &comp){
+ const auto &p = comp.priv();
+ EXPECT_EQ(3u, p.m_ins.size());
+ EXPECT_EQ(2u, p.m_outs.size());
+
+ EXPECT_TRUE(ProtoContainsT<GMat>(p.m_ins[0]));
+ EXPECT_TRUE(ProtoContainsT<GScalar>(p.m_ins[1]));
+ EXPECT_TRUE(ProtoContainsT<cv::detail::GOpaqueU>(p.m_ins[2]));
+ EXPECT_TRUE(cv::util::get<cv::detail::GOpaqueU>(p.m_ins[2]).holds<OpaqueT>());
+ EXPECT_FALSE(cv::util::get<cv::detail::GOpaqueU>(p.m_ins[2]).holds<WrongOpaqueT>());
+
+ EXPECT_TRUE(ProtoContainsT<GMat>(p.m_outs[0]));
+ EXPECT_TRUE(ProtoContainsT<GMat>(p.m_outs[1]));
+ };
+
+ check(tr.pattern());
+ check(tr.substitute());
+}
+
namespace
{
template<typename ArgT>
}
template<typename ArgT>
- typename std::enable_if<(cv::detail::GTypeTraits<ArgT>::kind != cv::detail::ArgKind::GARRAY), void>::type
+ typename std::enable_if<(cv::detail::GTypeTraits<ArgT>::kind == cv::detail::ArgKind::GOPAQUE), void>::type
+ arg_check(const cv::GProtoArg &arg)
+ {
+ EXPECT_TRUE(ProtoContainsT<cv::detail::GOpaqueU>(arg));
+ EXPECT_TRUE(cv::util::get<cv::detail::GOpaqueU>(arg).holds<OpaqueT>());
+ EXPECT_FALSE(cv::util::get<cv::detail::GOpaqueU>(arg).holds<WrongOpaqueT>());
+ }
+
+ template<typename ArgT>
+ typename std::enable_if<(cv::detail::GTypeTraits<ArgT>::kind != cv::detail::ArgKind::GARRAY &&
+ cv::detail::GTypeTraits<ArgT>::kind != cv::detail::ArgKind::GOPAQUE), void>::type
arg_check(const cv::GProtoArg &arg)
{
EXPECT_TRUE(ProtoContainsT<ArgT>(arg));
transformTest<gscalar_in_garr_out, GScalar, GArray<ArrayT>>();
}
+TEST(KernelPackageTransform, gop_in_gmat_out)
+{
+ transformTest<gop_in_gmat_out, GOpaque<OpaqueT>, GMat>();
+}
+
+TEST(KernelPackageTransform, gmat_in_gop_out)
+{
+ transformTest<gmat_in_gop_out, GMat, GOpaque<OpaqueT>>();
+}
+
+TEST(KernelPackageTransform, gop_in_gscalar_out)
+{
+ transformTest<gop_in_gscalar_out, GOpaque<OpaqueT>, GScalar>();
+}
+
+TEST(KernelPackageTransform, gscalar_in_gop_out)
+{
+ transformTest<gscalar_in_gop_out, GScalar, GOpaque<OpaqueT>>();
+}
+
} // namespace opencv_test
, Expected<cv::GArray<float>, cv::detail::ArgKind::GARRAY>
, Expected<cv::GArray<cv::Point>, cv::detail::ArgKind::GARRAY>
, Expected<cv::GArray<cv::Rect>, cv::detail::ArgKind::GARRAY>
+ , Expected<cv::GOpaque<int>, cv::detail::ArgKind::GOPAQUE>
+ , Expected<cv::GOpaque<float>, cv::detail::ArgKind::GOPAQUE>
+ , Expected<cv::GOpaque<cv::Point>, cv::detail::ArgKind::GOPAQUE>
+ , Expected<cv::GOpaque<cv::Rect>, cv::detail::ArgKind::GOPAQUE>
// Built-in types
, Expected<int, cv::detail::ArgKind::OPAQUE_VAL>
"GArray<int> has custom marshalling logic");
static_assert(cv::detail::has_custom_wrap<cv::GArray<std::string> >::value,
"GArray<int> has custom marshalling logic");
+
+ static_assert(cv::detail::has_custom_wrap<cv::GOpaque<int> >::value,
+ "GOpaque<int> has custom marshalling logic");
+ static_assert(cv::detail::has_custom_wrap<cv::GOpaque<std::string> >::value,
+ "GOpaque<int> has custom marshalling logic");
}
TEST(GArg, GArrayU)
EXPECT_NO_THROW(arg2.get<cv::detail::GArrayU>());
}
+TEST(GArg, GOpaqueU)
+{
+ // Placing a GOpaque<T> into GArg automatically strips it to GOpaqueU
+ cv::GArg arg1 = cv::GArg(cv::GOpaque<int>());
+ EXPECT_NO_THROW(arg1.get<cv::detail::GOpaqueU>());
+
+ cv::GArg arg2 = cv::GArg(cv::GOpaque<cv::Point>());
+ EXPECT_NO_THROW(arg2.get<cv::detail::GOpaqueU>());
+}
+
} // namespace opencv_test