Unverified Commit 0d456f91 authored by Alexey Smirnov's avatar Alexey Smirnov Committed by GitHub

Merge pull request #16118 from smirnov-alexey:as/gopaque

G-API: GOpaque implementation

* Stub initial copypasted solution

* Fix mov test and add a couple of others

* Fix warnings

* More code coverage and tests

* fix macos warning

* address review comments

* Address review comments and fix indentation

* Fix build on armv7
parent 2ced568d
...@@ -44,6 +44,7 @@ set(gapi_srcs ...@@ -44,6 +44,7 @@ set(gapi_srcs
src/api/gorigin.cpp src/api/gorigin.cpp
src/api/gmat.cpp src/api/gmat.cpp
src/api/garray.cpp src/api/garray.cpp
src/api/gopaque.cpp
src/api/gscalar.cpp src/api/gscalar.cpp
src/api/gkernel.cpp src/api/gkernel.cpp
src/api/gbackend.cpp src/api/gbackend.cpp
......
...@@ -94,9 +94,14 @@ public: ...@@ -94,9 +94,14 @@ public:
{ {
return outVecRef(output).wref<T>(); return outVecRef(output).wref<T>();
} }
template<typename T> T& outOpaqueR(int output) // FIXME: the same issue
{
return outOpaqueRef(output).wref<T>();
}
protected: protected:
detail::VectorRef& outVecRef(int output); detail::VectorRef& outVecRef(int output);
detail::OpaqueRef& outOpaqueRef(int output);
std::vector<GArg> m_args; std::vector<GArg> m_args;
...@@ -145,12 +150,31 @@ template<typename U> struct get_in<cv::GArray<U> > ...@@ -145,12 +150,31 @@ template<typename U> struct get_in<cv::GArray<U> >
{ {
static const std::vector<U>& get(GCPUContext &ctx, int idx) { return ctx.inArg<VectorRef>(idx).rref<U>(); } 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 //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> > 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 template<class T> struct get_in
{ {
static T get(GCPUContext &ctx, int idx) { return ctx.inArg<T>(idx); } static T get(GCPUContext &ctx, int idx) { return ctx.inArg<T>(idx); }
...@@ -229,6 +253,13 @@ template<typename U> struct get_out<cv::GArray<U>> ...@@ -229,6 +253,13 @@ template<typename U> struct get_out<cv::GArray<U>>
return ctx.outVecR<U>(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> template<typename, typename, typename>
struct OCVCallHelper; struct OCVCallHelper;
......
...@@ -200,6 +200,14 @@ template<typename U> struct fluid_get_in<cv::GArray<U>> ...@@ -200,6 +200,14 @@ template<typename U> struct fluid_get_in<cv::GArray<U>>
} }
}; };
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 template<class T> struct fluid_get_in
{ {
static const T& get(const cv::GArgs &in_args, int idx) static const T& get(const cv::GArgs &in_args, int idx)
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <opencv2/gapi/gmat.hpp> #include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/gscalar.hpp> #include <opencv2/gapi/gscalar.hpp>
#include <opencv2/gapi/garray.hpp> #include <opencv2/gapi/garray.hpp>
#include <opencv2/gapi/gopaque.hpp>
#include <opencv2/gapi/gtype_traits.hpp> #include <opencv2/gapi/gtype_traits.hpp>
#include <opencv2/gapi/gmetaarg.hpp> #include <opencv2/gapi/gmetaarg.hpp>
#include <opencv2/gapi/own/scalar.hpp> #include <opencv2/gapi/own/scalar.hpp>
...@@ -96,7 +97,8 @@ using GRunArg = util::variant< ...@@ -96,7 +97,8 @@ using GRunArg = util::variant<
cv::gapi::wip::IStreamSource::Ptr, cv::gapi::wip::IStreamSource::Ptr,
cv::gapi::own::Mat, cv::gapi::own::Mat,
cv::gapi::own::Scalar, cv::gapi::own::Scalar,
cv::detail::VectorRef cv::detail::VectorRef,
cv::detail::OpaqueRef
>; >;
using GRunArgs = std::vector<GRunArg>; using GRunArgs = std::vector<GRunArg>;
...@@ -128,7 +130,8 @@ using GRunArgP = util::variant< ...@@ -128,7 +130,8 @@ using GRunArgP = util::variant<
#endif // !defined(GAPI_STANDALONE) #endif // !defined(GAPI_STANDALONE)
cv::gapi::own::Mat*, cv::gapi::own::Mat*,
cv::gapi::own::Scalar*, cv::gapi::own::Scalar*,
cv::detail::VectorRef cv::detail::VectorRef,
cv::detail::OpaqueRef
>; >;
using GRunArgsP = std::vector<GRunArgP>; using GRunArgsP = std::vector<GRunArgP>;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <opencv2/gapi/gmat.hpp> // GMat #include <opencv2/gapi/gmat.hpp> // GMat
#include <opencv2/gapi/gscalar.hpp> // GScalar #include <opencv2/gapi/gscalar.hpp> // GScalar
#include <opencv2/gapi/garray.hpp> // GArray<T> #include <opencv2/gapi/garray.hpp> // GArray<T>
#include <opencv2/gapi/gopaque.hpp> // GOpaque<T>
namespace cv { namespace cv {
...@@ -46,6 +47,11 @@ public: ...@@ -46,6 +47,11 @@ public:
return GArray<T>(yieldArray(output)); return GArray<T>(yieldArray(output));
} }
template<class T> GOpaque<T> yieldOpaque(int output = 0)
{
return GOpaque<T>(yieldOpaque(output));
}
// Internal use only // Internal use only
Priv& priv(); Priv& priv();
const Priv& priv() const; const Priv& priv() const;
...@@ -55,8 +61,9 @@ protected: ...@@ -55,8 +61,9 @@ protected:
void setArgs(std::vector<GArg> &&args); 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::GArrayU yieldArray(int output = 0);
detail::GOpaqueU yieldOpaque(int output = 0);
}; };
} // namespace cv } // namespace cv
......
...@@ -44,6 +44,7 @@ enum class GShape: int ...@@ -44,6 +44,7 @@ enum class GShape: int
GMAT, GMAT,
GSCALAR, GSCALAR,
GARRAY, GARRAY,
GOPAQUE,
}; };
struct GCompileArg; struct GCompileArg;
......
...@@ -65,6 +65,16 @@ template<typename U> struct get_compound_in<cv::GArray<U>> ...@@ -65,6 +65,16 @@ template<typename U> struct get_compound_in<cv::GArray<U>>
} }
}; };
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> template<typename, typename, typename>
struct GCompoundCallHelper; struct GCompoundCallHelper;
......
...@@ -74,6 +74,10 @@ namespace detail ...@@ -74,6 +74,10 @@ namespace detail
{ {
static inline cv::GArray<U> yield(cv::GCall &call, int i) { return call.yieldArray<U>(i); } 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 } // anonymous namespace
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
...@@ -87,7 +91,8 @@ namespace detail ...@@ -87,7 +91,8 @@ namespace detail
template<> struct MetaType<cv::GMat> { using type = GMatDesc; }; template<> struct MetaType<cv::GMat> { using type = GMatDesc; };
template<> struct MetaType<cv::GMatP> { using type = GMatDesc; }; template<> struct MetaType<cv::GMatP> { using type = GMatDesc; };
template<> struct MetaType<cv::GScalar> { using type = GScalarDesc; }; 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 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 // 2. Hacky test based on MetaType to check if we operate on G-* type or not
......
...@@ -46,6 +46,7 @@ struct GOrigin; ...@@ -46,6 +46,7 @@ struct GOrigin;
* cv::GMat | cv::Mat * cv::GMat | cv::Mat
* cv::GScalar | cv::Scalar * cv::GScalar | cv::Scalar
* `cv::GArray<T>` | std::vector<T> * `cv::GArray<T>` | std::vector<T>
* `cv::GOpaque<T>` | T
*/ */
class GAPI_EXPORTS GMat class GAPI_EXPORTS GMat
{ {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <opencv2/gapi/gmat.hpp> #include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/gscalar.hpp> #include <opencv2/gapi/gscalar.hpp>
#include <opencv2/gapi/garray.hpp> #include <opencv2/gapi/garray.hpp>
#include <opencv2/gapi/gopaque.hpp>
namespace cv namespace cv
{ {
...@@ -36,6 +37,7 @@ using GMetaArg = util::variant ...@@ -36,6 +37,7 @@ using GMetaArg = util::variant
, GMatDesc , GMatDesc
, GScalarDesc , GScalarDesc
, GArrayDesc , GArrayDesc
, GOpaqueDesc
>; >;
GAPI_EXPORTS std::ostream& operator<<(std::ostream& os, const GMetaArg &); GAPI_EXPORTS std::ostream& operator<<(std::ostream& os, const GMetaArg &);
...@@ -52,6 +54,7 @@ namespace detail ...@@ -52,6 +54,7 @@ namespace detail
template<> struct is_meta_descr<GMatDesc> : std::true_type {}; template<> struct is_meta_descr<GMatDesc> : std::true_type {};
template<> struct is_meta_descr<GScalarDesc> : 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<GArrayDesc> : std::true_type {};
template<> struct is_meta_descr<GOpaqueDesc> : std::true_type {};
template<typename... Ts> template<typename... Ts>
using are_meta_descrs = all_satisfy<is_meta_descr, Ts...>; using are_meta_descrs = all_satisfy<is_meta_descr, Ts...>;
......
// 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
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <opencv2/gapi/gmat.hpp> #include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/gscalar.hpp> #include <opencv2/gapi/gscalar.hpp>
#include <opencv2/gapi/garray.hpp> #include <opencv2/gapi/garray.hpp>
#include <opencv2/gapi/gopaque.hpp>
#include <opencv2/gapi/garg.hpp> #include <opencv2/gapi/garg.hpp>
#include <opencv2/gapi/gmetaarg.hpp> #include <opencv2/gapi/gmetaarg.hpp>
...@@ -36,7 +37,8 @@ using GProtoArg = util::variant ...@@ -36,7 +37,8 @@ using GProtoArg = util::variant
< GMat < GMat
, GMatP , GMatP
, GScalar , GScalar
, detail::GArrayU // instead of GArray<T> , detail::GArrayU // instead of GArray<T>
, detail::GOpaqueU // instead of GOpaque<T>
>; >;
using GProtoArgs = std::vector<GProtoArg>; using GProtoArgs = std::vector<GProtoArg>;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <opencv2/gapi/gmat.hpp> #include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/gscalar.hpp> #include <opencv2/gapi/gscalar.hpp>
#include <opencv2/gapi/garray.hpp> #include <opencv2/gapi/garray.hpp>
#include <opencv2/gapi/gopaque.hpp>
#include <opencv2/gapi/streaming/source.hpp> #include <opencv2/gapi/streaming/source.hpp>
#include <opencv2/gapi/gcommon.hpp> #include <opencv2/gapi/gcommon.hpp>
#include <opencv2/gapi/own/convert.hpp> #include <opencv2/gapi/own/convert.hpp>
...@@ -36,7 +37,8 @@ namespace detail ...@@ -36,7 +37,8 @@ namespace detail
GMAT, // a cv::GMat GMAT, // a cv::GMat
GMATP, // a cv::GMatP GMATP, // a cv::GMatP
GSCALAR, // a cv::GScalar 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 // Describe G-API types (G-types) with traits. Mostly used by
...@@ -73,6 +75,16 @@ namespace detail ...@@ -73,6 +75,16 @@ namespace detail
static cv::detail::VectorRef wrap_in (const std::vector<T> &t) { return detail::VectorRef(t); } 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); } 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. // Tests if Trait for type T requires extra marshalling ("custom wrap") or not.
// If Traits<T> has wrap_value() defined, it does. // If Traits<T> has wrap_value() defined, it does.
...@@ -100,6 +112,7 @@ namespace detail ...@@ -100,6 +112,7 @@ namespace detail
template<> struct GTypeOf<cv::gapi::own::Mat> { using type = cv::GMat; }; template<> struct GTypeOf<cv::gapi::own::Mat> { using type = cv::GMat; };
template<> struct GTypeOf<cv::gapi::own::Scalar> { using type = cv::GScalar; }; 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<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 // 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. // 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<> struct GTypeOf<cv::gapi::wip::IStreamSource::Ptr> { using type = cv::GMat;};
...@@ -164,7 +177,6 @@ namespace detail ...@@ -164,7 +177,6 @@ namespace detail
template<typename T> using wrap_gapi_helper = WrapValue<typename std::decay<T>::type>; 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>; template<typename T> using wrap_host_helper = WrapValue<typename std::decay<g_type_of_t<T> >::type>;
} // namespace detail } // namespace detail
} // namespace cv } // namespace cv
......
...@@ -25,13 +25,15 @@ namespace detail ...@@ -25,13 +25,15 @@ namespace detail
template<typename T> struct ProtoToParam; template<typename T> struct ProtoToParam;
template<> struct ProtoToParam<cv::GMat> { using type = cv::Mat; }; template<> struct ProtoToParam<cv::GMat> { using type = cv::Mat; };
template<> struct ProtoToParam<cv::GScalar> { using type = cv::Scalar; }; 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> using ProtoToParamT = typename ProtoToParam<T>::type;
template<typename T> struct ProtoToMeta; template<typename T> struct ProtoToMeta;
template<> struct ProtoToMeta<cv::GMat> { using type = cv::GMatDesc; }; template<> struct ProtoToMeta<cv::GMat> { using type = cv::GMatDesc; };
template<> struct ProtoToMeta<cv::GScalar> { using type = cv::GScalarDesc; }; 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; template<typename T> using ProtoToMetaT = typename ProtoToMeta<T>::type;
//workaround for MSVC 19.0 bug //workaround for MSVC 19.0 bug
......
...@@ -68,9 +68,14 @@ public: ...@@ -68,9 +68,14 @@ public:
{ {
return outVecRef(output).wref<T>(); return outVecRef(output).wref<T>();
} }
template<typename T> T& outOpaqueR(int output) // FIXME: the same issue
{
return outOpaqueRef(output).wref<T>();
}
protected: protected:
detail::VectorRef& outVecRef(int output); detail::VectorRef& outVecRef(int output);
detail::VectorRef& outOpaqueRef(int output);
std::vector<GArg> m_args; std::vector<GArg> m_args;
std::unordered_map<std::size_t, GRunArgP> m_results; std::unordered_map<std::size_t, GRunArgP> m_results;
...@@ -111,6 +116,10 @@ template<typename U> struct ocl_get_in<cv::GArray<U> > ...@@ -111,6 +116,10 @@ template<typename U> struct ocl_get_in<cv::GArray<U> >
{ {
static const std::vector<U>& get(GOCLContext &ctx, int idx) { return ctx.inArg<VectorRef>(idx).rref<U>(); } 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 template<class T> struct ocl_get_in
{ {
static T get(GOCLContext &ctx, int idx) { return ctx.inArg<T>(idx); } static T get(GOCLContext &ctx, int idx) { return ctx.inArg<T>(idx); }
...@@ -184,6 +193,10 @@ template<typename U> struct ocl_get_out<cv::GArray<U> > ...@@ -184,6 +193,10 @@ template<typename U> struct ocl_get_out<cv::GArray<U> >
{ {
static std::vector<U>& get(GOCLContext &ctx, int idx) { return ctx.outVecR<U>(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> template<typename, typename, typename>
struct OCLCallHelper; struct OCLCallHelper;
......
...@@ -168,6 +168,10 @@ void bindInArg(Mag& mag, const RcDesc &rc, const GRunArg &arg, bool is_umat) ...@@ -168,6 +168,10 @@ void bindInArg(Mag& mag, const RcDesc &rc, const GRunArg &arg, bool is_umat)
mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg); mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg);
break; break;
case GShape::GOPAQUE:
mag.template slot<cv::detail::OpaqueRef>()[rc.id] = util::get<cv::detail::OpaqueRef>(arg);
break;
default: default:
util::throw_error(std::logic_error("Unsupported GShape type")); util::throw_error(std::logic_error("Unsupported GShape type"));
} }
...@@ -233,6 +237,10 @@ void bindOutArg(Mag& mag, const RcDesc &rc, const GRunArgP &arg, bool is_umat) ...@@ -233,6 +237,10 @@ void bindOutArg(Mag& mag, const RcDesc &rc, const GRunArgP &arg, bool is_umat)
mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg); mag.template slot<cv::detail::VectorRef>()[rc.id] = util::get<cv::detail::VectorRef>(arg);
break; break;
case GShape::GOPAQUE:
mag.template slot<cv::detail::OpaqueRef>()[rc.id] = util::get<cv::detail::OpaqueRef>(arg);
break;
default: default:
util::throw_error(std::logic_error("Unsupported GShape type")); util::throw_error(std::logic_error("Unsupported GShape type"));
break; break;
...@@ -251,6 +259,11 @@ void resetInternalData(Mag& mag, const Data &d) ...@@ -251,6 +259,11 @@ void resetInternalData(Mag& mag, const Data &d)
(mag.template slot<cv::detail::VectorRef>()[d.rc]); (mag.template slot<cv::detail::VectorRef>()[d.rc]);
break; break;
case GShape::GOPAQUE:
util::get<cv::detail::ConstructOpaque>(d.ctor)
(mag.template slot<cv::detail::OpaqueRef>()[d.rc]);
break;
case GShape::GSCALAR: case GShape::GSCALAR:
mag.template slot<cv::gapi::own::Scalar>()[d.rc] = cv::gapi::own::Scalar(); mag.template slot<cv::gapi::own::Scalar>()[d.rc] = cv::gapi::own::Scalar();
break; break;
...@@ -272,9 +285,10 @@ cv::GRunArg getArg(const Mag& mag, const RcDesc &ref) ...@@ -272,9 +285,10 @@ cv::GRunArg getArg(const Mag& mag, const RcDesc &ref)
{ {
case GShape::GMAT: return GRunArg(mag.template slot<cv::gapi::own::Mat>().at(ref.id)); 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)); 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) // (and constructed by either bindIn/Out or resetInternal)
case GShape::GARRAY: return GRunArg(mag.template slot<cv::detail::VectorRef>().at(ref.id)); 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: default:
util::throw_error(std::logic_error("Unsupported GShape type")); util::throw_error(std::logic_error("Unsupported GShape type"));
break; break;
...@@ -297,7 +311,7 @@ cv::GRunArgP getObjPtr(Mag& mag, const RcDesc &rc, bool is_umat) ...@@ -297,7 +311,7 @@ cv::GRunArgP getObjPtr(Mag& mag, const RcDesc &rc, bool is_umat)
else else
return GRunArgP(&mag.template slot<cv::gapi::own::Mat>()[rc.id]); 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]); 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) // (and constructor by either bindIn/Out or resetInternal)
case GShape::GARRAY: case GShape::GARRAY:
// FIXME(DM): For some absolutely unknown to me reason, move // FIXME(DM): For some absolutely unknown to me reason, move
...@@ -307,6 +321,14 @@ cv::GRunArgP getObjPtr(Mag& mag, const RcDesc &rc, bool is_umat) ...@@ -307,6 +321,14 @@ cv::GRunArgP getObjPtr(Mag& mag, const RcDesc &rc, bool is_umat)
// debugging this!!!1 // debugging this!!!1
return GRunArgP(const_cast<const Mag&>(mag) return GRunArgP(const_cast<const Mag&>(mag)
.template slot<cv::detail::VectorRef>().at(rc.id)); .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: default:
util::throw_error(std::logic_error("Unsupported GShape type")); util::throw_error(std::logic_error("Unsupported GShape type"));
break; break;
...@@ -320,6 +342,9 @@ void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat) ...@@ -320,6 +342,9 @@ void writeBack(const Mag& mag, const RcDesc &rc, GRunArgP &g_arg, bool is_umat)
case GShape::GARRAY: case GShape::GARRAY:
// Do nothing - should we really do anything here? // Do nothing - should we really do anything here?
break; break;
case GShape::GOPAQUE:
// Do nothing - should we really do anything here?
break;
case GShape::GMAT: case GShape::GMAT:
{ {
......
...@@ -64,6 +64,11 @@ cv::detail::GArrayU cv::GCall::yieldArray(int output) ...@@ -64,6 +64,11 @@ cv::detail::GArrayU cv::GCall::yieldArray(int output)
return cv::detail::GArrayU(m_priv->m_node, output); 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() cv::GCall::Priv& cv::GCall::priv()
{ {
return *m_priv; return *m_priv;
......
// 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;
}
}
...@@ -34,6 +34,9 @@ const cv::GOrigin& cv::gimpl::proto::origin_of(const cv::GProtoArg &arg) ...@@ -34,6 +34,9 @@ const cv::GOrigin& cv::gimpl::proto::origin_of(const cv::GProtoArg &arg)
case cv::GProtoArg::index_of<cv::detail::GArrayU>(): case cv::GProtoArg::index_of<cv::detail::GArrayU>():
return util::get<cv::detail::GArrayU>(arg).priv(); 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: default:
util::throw_error(std::logic_error("Unsupported GProtoArg type")); util::throw_error(std::logic_error("Unsupported GProtoArg type"));
} }
...@@ -59,6 +62,7 @@ bool cv::gimpl::proto::is_dynamic(const cv::GArg& arg) ...@@ -59,6 +62,7 @@ bool cv::gimpl::proto::is_dynamic(const cv::GArg& arg)
case detail::ArgKind::GMATP: case detail::ArgKind::GMATP:
case detail::ArgKind::GSCALAR: case detail::ArgKind::GSCALAR:
case detail::ArgKind::GARRAY: case detail::ArgKind::GARRAY:
case detail::ArgKind::GOPAQUE:
return true; return true;
default: default:
...@@ -85,6 +89,7 @@ cv::GProtoArg cv::gimpl::proto::rewrap(const cv::GArg &arg) ...@@ -85,6 +89,7 @@ cv::GProtoArg cv::gimpl::proto::rewrap(const cv::GArg &arg)
case detail::ArgKind::GMATP: return GProtoArg(arg.get<cv::GMatP>()); case detail::ArgKind::GMATP: return GProtoArg(arg.get<cv::GMatP>());
case detail::ArgKind::GSCALAR: return GProtoArg(arg.get<cv::GScalar>()); case detail::ArgKind::GSCALAR: return GProtoArg(arg.get<cv::GScalar>());
case detail::ArgKind::GARRAY: return GProtoArg(arg.get<cv::detail::GArrayU>()); 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")); default: util::throw_error(std::logic_error("Unsupported GArg type"));
} }
} }
...@@ -110,6 +115,9 @@ cv::GMetaArg cv::descr_of(const cv::GRunArg &arg) ...@@ -110,6 +115,9 @@ cv::GMetaArg cv::descr_of(const cv::GRunArg &arg)
case GRunArg::index_of<cv::detail::VectorRef>(): case GRunArg::index_of<cv::detail::VectorRef>():
return cv::GMetaArg(util::get<cv::detail::VectorRef>(arg).descr_of()); 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>(): case GRunArg::index_of<cv::gapi::wip::IStreamSource::Ptr>():
return cv::util::get<cv::gapi::wip::IStreamSource::Ptr>(arg)->descr_of(); return cv::util::get<cv::gapi::wip::IStreamSource::Ptr>(arg)->descr_of();
...@@ -136,6 +144,7 @@ cv::GMetaArg cv::descr_of(const cv::GRunArgP &argp) ...@@ -136,6 +144,7 @@ cv::GMetaArg cv::descr_of(const cv::GRunArgP &argp)
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::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::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::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")); default: util::throw_error(std::logic_error("Unsupported GRunArgP type"));
} }
} }
...@@ -154,6 +163,7 @@ bool cv::can_describe(const GMetaArg& meta, const GRunArgP& argp) ...@@ -154,6 +163,7 @@ bool cv::can_describe(const GMetaArg& meta, const GRunArgP& argp)
util::get<GMatDesc>(meta).canDescribe(*util::get<cv::gapi::own::Mat*>(argp)); 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::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::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")); default: util::throw_error(std::logic_error("Unsupported GRunArgP type"));
} }
} }
...@@ -172,6 +182,7 @@ bool cv::can_describe(const GMetaArg& meta, const GRunArg& arg) ...@@ -172,6 +182,7 @@ bool cv::can_describe(const GMetaArg& meta, const GRunArg& arg)
util::get<GMatDesc>(meta).canDescribe(util::get<cv::gapi::own::Mat>(arg)); 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::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::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 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")); default: util::throw_error(std::logic_error("Unsupported GRunArg type"));
} }
...@@ -207,6 +218,10 @@ std::ostream& operator<<(std::ostream& os, const cv::GMetaArg &arg) ...@@ -207,6 +218,10 @@ std::ostream& operator<<(std::ostream& os, const cv::GMetaArg &arg)
case cv::GMetaArg::index_of<cv::GArrayDesc>(): case cv::GMetaArg::index_of<cv::GArrayDesc>():
os << util::get<cv::GArrayDesc>(arg); os << util::get<cv::GArrayDesc>(arg);
break; break;
case cv::GMetaArg::index_of<cv::GOpaqueDesc>():
os << util::get<cv::GOpaqueDesc>(arg);
break;
default: default:
GAPI_Assert(false); GAPI_Assert(false);
} }
......
...@@ -46,9 +46,9 @@ namespace magazine { ...@@ -46,9 +46,9 @@ namespace magazine {
} // namespace magazine } // namespace magazine
#if !defined(GAPI_STANDALONE) #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 #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 #endif
namespace magazine namespace magazine
......
...@@ -113,7 +113,8 @@ cv::GArg cv::gimpl::GCPUExecutable::packArg(const GArg &arg) ...@@ -113,7 +113,8 @@ cv::GArg cv::gimpl::GCPUExecutable::packArg(const GArg &arg)
// FIXME: this check has to be done somewhere in compilation stage. // FIXME: this check has to be done somewhere in compilation stage.
GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT
&& arg.kind != cv::detail::ArgKind::GSCALAR && 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) if (arg.kind != cv::detail::ArgKind::GOBJREF)
{ {
...@@ -129,9 +130,10 @@ cv::GArg cv::gimpl::GCPUExecutable::packArg(const GArg &arg) ...@@ -129,9 +130,10 @@ cv::GArg cv::gimpl::GCPUExecutable::packArg(const GArg &arg)
{ {
case GShape::GMAT: return GArg(m_res.slot<cv::gapi::own::Mat>() [ref.id]); 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]); 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) // (and constructed by either bindIn/Out or resetInternal)
case GShape::GARRAY: return GArg(m_res.slot<cv::detail::VectorRef>().at(ref.id)); 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: default:
util::throw_error(std::logic_error("Unsupported GShape type")); util::throw_error(std::logic_error("Unsupported GShape type"));
break; break;
......
...@@ -36,6 +36,11 @@ cv::detail::VectorRef& cv::GCPUContext::outVecRef(int output) ...@@ -36,6 +36,11 @@ cv::detail::VectorRef& cv::GCPUContext::outVecRef(int output)
return util::get<cv::detail::VectorRef>(m_results.at(output)); 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() cv::GCPUKernel::GCPUKernel()
{ {
} }
......
...@@ -1250,6 +1250,7 @@ void cv::gimpl::GFluidExecutable::bindInArg(const cv::gimpl::RcDesc &rc, const G ...@@ -1250,6 +1250,7 @@ void cv::gimpl::GFluidExecutable::bindInArg(const cv::gimpl::RcDesc &rc, const G
case GShape::GMAT: m_buffers[m_id_map.at(rc.id)].priv().bindTo(util::get<cv::gapi::own::Mat>(arg), true); break; 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::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::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;
} }
} }
...@@ -1292,7 +1293,8 @@ void cv::gimpl::GFluidExecutable::packArg(cv::GArg &in_arg, const cv::GArg &op_a ...@@ -1292,7 +1293,8 @@ void cv::gimpl::GFluidExecutable::packArg(cv::GArg &in_arg, const cv::GArg &op_a
{ {
GAPI_Assert(op_arg.kind != cv::detail::ArgKind::GMAT GAPI_Assert(op_arg.kind != cv::detail::ArgKind::GMAT
&& op_arg.kind != cv::detail::ArgKind::GSCALAR && 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) if (op_arg.kind == cv::detail::ArgKind::GOBJREF)
{ {
...@@ -1305,6 +1307,10 @@ void cv::gimpl::GFluidExecutable::packArg(cv::GArg &in_arg, const cv::GArg &op_a ...@@ -1305,6 +1307,10 @@ void cv::gimpl::GFluidExecutable::packArg(cv::GArg &in_arg, const cv::GArg &op_a
{ {
in_arg = GArg(m_res.slot<cv::detail::VectorRef>()[ref.id]); 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]);
}
} }
} }
......
...@@ -129,7 +129,7 @@ class GFluidExecutable final: public GIslandExecutable ...@@ -129,7 +129,7 @@ class GFluidExecutable final: public GIslandExecutable
std::vector<FluidAgent*> m_script; 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; Magazine m_res;
std::size_t m_num_int_buffers; // internal buffers counter (m_buffers - num_scratch) std::size_t m_num_int_buffers; // internal buffers counter (m_buffers - num_scratch)
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <opencv2/gapi/gcommon.hpp> #include <opencv2/gapi/gcommon.hpp>
#include <opencv2/gapi/garray.hpp> #include <opencv2/gapi/garray.hpp>
#include <opencv2/gapi/gopaque.hpp>
#include <opencv2/gapi/util/any.hpp> #include <opencv2/gapi/util/any.hpp>
#include <opencv2/gapi/gtype_traits.hpp> #include <opencv2/gapi/gtype_traits.hpp>
#include <opencv2/gapi/infer.hpp> #include <opencv2/gapi/infer.hpp>
...@@ -396,6 +397,10 @@ cv::GArg cv::gimpl::ie::GIEExecutable::packArg(const cv::GArg &arg) { ...@@ -396,6 +397,10 @@ cv::GArg cv::gimpl::ie::GIEExecutable::packArg(const cv::GArg &arg) {
// (and constructed by either bindIn/Out or resetInternal) // (and constructed by either bindIn/Out or resetInternal)
case GShape::GARRAY: return GArg(m_res.slot<cv::detail::VectorRef>().at(ref.id)); 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: default:
util::throw_error(std::logic_error("Unsupported GShape type")); util::throw_error(std::logic_error("Unsupported GShape type"));
break; break;
......
...@@ -113,7 +113,8 @@ cv::GArg cv::gimpl::GOCLExecutable::packArg(const GArg &arg) ...@@ -113,7 +113,8 @@ cv::GArg cv::gimpl::GOCLExecutable::packArg(const GArg &arg)
// FIXME: this check has to be done somewhere in compilation stage. // FIXME: this check has to be done somewhere in compilation stage.
GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT
&& arg.kind != cv::detail::ArgKind::GSCALAR && 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) if (arg.kind != cv::detail::ArgKind::GOBJREF)
{ {
...@@ -129,9 +130,12 @@ cv::GArg cv::gimpl::GOCLExecutable::packArg(const GArg &arg) ...@@ -129,9 +130,12 @@ cv::GArg cv::gimpl::GOCLExecutable::packArg(const GArg &arg)
{ {
case GShape::GMAT: return GArg(m_res.slot<cv::UMat>()[ref.id]); 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]); 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) // (and constructed by either bindIn/Out or resetInternal)
case GShape::GARRAY: return GArg(m_res.slot<cv::detail::VectorRef>().at(ref.id)); 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: default:
util::throw_error(std::logic_error("Unsupported GShape type")); util::throw_error(std::logic_error("Unsupported GShape type"));
break; break;
......
...@@ -276,7 +276,8 @@ cv::GArg cv::gimpl::GPlaidMLExecutable::packArg(const GArg &arg) ...@@ -276,7 +276,8 @@ cv::GArg cv::gimpl::GPlaidMLExecutable::packArg(const GArg &arg)
{ {
GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT GAPI_Assert( arg.kind != cv::detail::ArgKind::GMAT
&& arg.kind != cv::detail::ArgKind::GSCALAR && 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) if (arg.kind != cv::detail::ArgKind::GOBJREF)
{ {
......
...@@ -332,6 +332,9 @@ void cv::gimpl::GCompiler::validateInputMeta() ...@@ -332,6 +332,9 @@ void cv::gimpl::GCompiler::validateInputMeta()
case GProtoArg::index_of<cv::detail::GArrayU>(): case GProtoArg::index_of<cv::detail::GArrayU>():
return util::holds_alternative<cv::GArrayDesc>(meta); return util::holds_alternative<cv::GArrayDesc>(meta);
case GProtoArg::index_of<cv::detail::GOpaqueU>():
return util::holds_alternative<cv::GOpaqueDesc>(meta);
default: default:
GAPI_Assert(false); GAPI_Assert(false);
} }
......
...@@ -16,13 +16,14 @@ namespace cv ...@@ -16,13 +16,14 @@ namespace cv
namespace gimpl 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 // FIXME: Replace construct-only API with a more generic one
// (probably with bits of introspection) // (probably with bits of introspection)
// Not required for non-user-defined types (GMat, GScalar, etc) // Not required for non-user-defined types (GMat, GScalar, etc)
using HostCtor = util::variant using HostCtor = util::variant
< util::monostate < util::monostate
, detail::ConstructVec , detail::ConstructVec
, detail::ConstructOpaque
>; >;
using ConstVal = util::variant using ConstVal = util::variant
......
...@@ -32,6 +32,7 @@ void dumpDot(const ade::Graph &g, std::ostream& os) ...@@ -32,6 +32,7 @@ void dumpDot(const ade::Graph &g, std::ostream& os)
{cv::GShape::GMAT, "GMat"}, {cv::GShape::GMAT, "GMat"},
{cv::GShape::GSCALAR, "GScalar"}, {cv::GShape::GSCALAR, "GScalar"},
{cv::GShape::GARRAY, "GArray"}, {cv::GShape::GARRAY, "GArray"},
{cv::GShape::GOPAQUE, "GOpaque"},
}; };
auto format_op_label = [&gr](ade::NodeHandle nh) -> std::string { auto format_op_label = [&gr](ade::NodeHandle nh) -> std::string {
......
// 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
...@@ -22,10 +22,27 @@ using GMat2 = std::tuple<GMat, GMat>; ...@@ -22,10 +22,27 @@ using GMat2 = std::tuple<GMat, GMat>;
using GMat3 = std::tuple<GMat, GMat, GMat>; using GMat3 = std::tuple<GMat, GMat, GMat>;
using GScalar = cv::GScalar; using GScalar = cv::GScalar;
template <typename T> using GArray = cv::GArray<T>; template <typename T> using GArray = cv::GArray<T>;
template <typename T> using GOpaque = cv::GOpaque<T>;
using ArrayT = int; using ArrayT = int;
using WrongArrayT = char; 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") GAPI_TRANSFORM(gmat_in_gmat_out, <GMat(GMat)>, "gmat_in_gmat_out")
{ {
static GMat pattern(GMat) { return {}; } static GMat pattern(GMat) { return {}; }
...@@ -92,6 +109,36 @@ GAPI_TRANSFORM(gmat_gsc_garray_in_gmat2_out, <GMat2(GMat, GScalar, GArray<ArrayT ...@@ -92,6 +109,36 @@ GAPI_TRANSFORM(gmat_gsc_garray_in_gmat2_out, <GMat2(GMat, GScalar, GArray<ArrayT
static GMat2 substitute(GMat, GScalar, GArray<ArrayT>) { 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 } // anonymous namespace
TEST(KernelPackageTransform, CreatePackage) TEST(KernelPackageTransform, CreatePackage)
...@@ -108,10 +155,15 @@ TEST(KernelPackageTransform, CreatePackage) ...@@ -108,10 +155,15 @@ TEST(KernelPackageTransform, CreatePackage)
, garr_in_gscalar_out , garr_in_gscalar_out
, gscalar_in_garr_out , gscalar_in_garr_out
, gmat_gsc_garray_in_gmat2_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(); auto tr = pkg.get_transformations();
EXPECT_EQ(11u, tr.size()); EXPECT_EQ(16u, tr.size());
} }
TEST(KernelPackageTransform, Include) TEST(KernelPackageTransform, Include)
...@@ -164,6 +216,29 @@ TEST(KernelPackageTransform, gmat_gsc_garray_in_gmat2_out) ...@@ -164,6 +216,29 @@ TEST(KernelPackageTransform, gmat_gsc_garray_in_gmat2_out)
check(tr.substitute()); 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 namespace
{ {
template<typename ArgT> template<typename ArgT>
...@@ -176,7 +251,17 @@ namespace ...@@ -176,7 +251,17 @@ 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) arg_check(const cv::GProtoArg &arg)
{ {
EXPECT_TRUE(ProtoContainsT<ArgT>(arg)); EXPECT_TRUE(ProtoContainsT<ArgT>(arg));
...@@ -242,4 +327,24 @@ TEST(KernelPackageTransform, gscalar_in_garr_out) ...@@ -242,4 +327,24 @@ TEST(KernelPackageTransform, gscalar_in_garr_out)
transformTest<gscalar_in_garr_out, GScalar, GArray<ArrayT>>(); 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 } // namespace opencv_test
...@@ -37,6 +37,10 @@ using GArg_Test_Types = ::testing::Types ...@@ -37,6 +37,10 @@ using GArg_Test_Types = ::testing::Types
, Expected<cv::GArray<float>, cv::detail::ArgKind::GARRAY> , Expected<cv::GArray<float>, cv::detail::ArgKind::GARRAY>
, Expected<cv::GArray<cv::Point>, cv::detail::ArgKind::GARRAY> , Expected<cv::GArray<cv::Point>, cv::detail::ArgKind::GARRAY>
, Expected<cv::GArray<cv::Rect>, 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 // Built-in types
, Expected<int, cv::detail::ArgKind::OPAQUE_VAL> , Expected<int, cv::detail::ArgKind::OPAQUE_VAL>
...@@ -85,6 +89,11 @@ TEST(GArg, HasWrap) ...@@ -85,6 +89,11 @@ TEST(GArg, HasWrap)
"GArray<int> has custom marshalling logic"); "GArray<int> has custom marshalling logic");
static_assert(cv::detail::has_custom_wrap<cv::GArray<std::string> >::value, static_assert(cv::detail::has_custom_wrap<cv::GArray<std::string> >::value,
"GArray<int> has custom marshalling logic"); "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) TEST(GArg, GArrayU)
...@@ -97,5 +106,15 @@ TEST(GArg, GArrayU) ...@@ -97,5 +106,15 @@ TEST(GArg, GArrayU)
EXPECT_NO_THROW(arg2.get<cv::detail::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 } // namespace opencv_test
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment