From 3e538355e2740721ca8b0c20faf72b2e6d607ec7 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 9 Jun 2021 08:34:58 +0000 Subject: [PATCH 1/3] highgui: force loading of imgcodecs module - required for plugins on Linux (they use imwrite, but there is no link dependency) --- modules/highgui/src/plugin_wrapper.impl.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/highgui/src/plugin_wrapper.impl.hpp b/modules/highgui/src/plugin_wrapper.impl.hpp index 3fa2cfa11a..97aea69098 100644 --- a/modules/highgui/src/plugin_wrapper.impl.hpp +++ b/modules/highgui/src/plugin_wrapper.impl.hpp @@ -232,8 +232,12 @@ std::vector getPluginCandidates(const std::string& baseName) return results; } +// NB: require loading of imgcodecs module +static void* g_imwrite = (void*)imwrite; + void PluginUIBackendFactory::loadPlugin() { + CV_Assert(g_imwrite); for (const FileSystemPath_t& plugin : getPluginCandidates(baseName_)) { auto lib = std::make_shared(plugin); From f4abafb093c9fac4b230399b28bb3618acff9ed8 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 9 Jun 2021 08:36:32 +0000 Subject: [PATCH 2/3] highgui: update error messages if no builtin backend --- modules/highgui/CMakeLists.txt | 5 + modules/highgui/src/backend.cpp | 1 - modules/highgui/src/precomp.hpp | 3 + modules/highgui/src/registry.impl.hpp | 2 + modules/highgui/src/window.cpp | 169 +++++++++++++++++++++++++- 5 files changed, 176 insertions(+), 4 deletions(-) diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index a0f444fd52..b4d4b9f503 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -281,5 +281,10 @@ ocv_target_link_libraries(${the_module} LINK_PRIVATE ${tgts}) set(CONFIG_STR "// Auto-generated file #define OPENCV_HIGHGUI_BUILTIN_BACKEND_STR \"${OPENCV_HIGHGUI_BUILTIN_BACKEND}\" ") +if(OPENCV_HIGHGUI_BUILTIN_BACKEND STREQUAL "NONE") +set(CONFIG_STR "${CONFIG_STR} +#define OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND 1 +") +endif() ocv_update_file("${CMAKE_CURRENT_BINARY_DIR}/opencv_highgui_config.hpp" "${CONFIG_STR}") diff --git a/modules/highgui/src/backend.cpp b/modules/highgui/src/backend.cpp index 7c241ea907..9ea475cecc 100644 --- a/modules/highgui/src/backend.cpp +++ b/modules/highgui/src/backend.cpp @@ -2,7 +2,6 @@ // 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. #include "precomp.hpp" -#include "opencv_highgui_config.hpp" // generated by CMake #include "backend.hpp" #include diff --git a/modules/highgui/src/precomp.hpp b/modules/highgui/src/precomp.hpp index 275cc556ae..6ad5bce8b4 100644 --- a/modules/highgui/src/precomp.hpp +++ b/modules/highgui/src/precomp.hpp @@ -47,6 +47,9 @@ #endif #include "opencv2/highgui.hpp" +#if !defined(BUILD_PLUGIN) +#include "opencv_highgui_config.hpp" // generated by CMake +#endif #include "opencv2/core/utility.hpp" #if defined(__OPENCV_BUILD) diff --git a/modules/highgui/src/registry.impl.hpp b/modules/highgui/src/registry.impl.hpp index 9c50986a69..ccf81f9280 100644 --- a/modules/highgui/src/registry.impl.hpp +++ b/modules/highgui/src/registry.impl.hpp @@ -162,7 +162,9 @@ public: const BackendInfo& info = enabledBackends[i]; os << info.name << '(' << info.priority << ')'; } +#if !defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) os << " + BUILTIN(" OPENCV_HIGHGUI_BUILTIN_BACKEND_STR ")"; +#endif return os.str(); } diff --git a/modules/highgui/src/window.cpp b/modules/highgui/src/window.cpp index 7a4532e1b8..dca6ddbaf8 100644 --- a/modules/highgui/src/window.cpp +++ b/modules/highgui/src/window.cpp @@ -179,6 +179,14 @@ static void cleanupTrackbarCallbacksWithData_() using namespace cv::impl; +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) +static void deprecateNotFoundNoOpBehavior() +{ + CV_LOG_ONCE_WARNING(NULL, "This no-op behavior is deprecated. Future versions of OpenCV will trigger exception in this case"); +} +#define CV_NOT_FOUND_DEPRECATION deprecateNotFoundNoOpBehavior() +#endif + CV_IMPL void cvSetWindowProperty(const char* name, int prop_id, double prop_value) { CV_TRACE_FUNCTION(); @@ -193,6 +201,19 @@ CV_IMPL void cvSetWindowProperty(const char* name, int prop_id, double prop_valu } } +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) + auto backend = getCurrentUIBackend(); + if (backend) + { + CV_LOG_WARNING(NULL, "Can't find window with name: '" << name << "'. Do nothing"); + CV_NOT_FOUND_DEPRECATION; + } + else + { + CV_LOG_WARNING(NULL, "No UI backends available. Use OPENCV_LOG_LEVEL=DEBUG for investigation"); + } + return; +#else switch(prop_id) { //change between fullscreen or not. @@ -249,6 +270,7 @@ CV_IMPL void cvSetWindowProperty(const char* name, int prop_id, double prop_valu default:; } +#endif } /* return -1 if error */ @@ -268,6 +290,19 @@ CV_IMPL double cvGetWindowProperty(const char* name, int prop_id) } } +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) + auto backend = getCurrentUIBackend(); + if (backend) + { + CV_LOG_WARNING(NULL, "Can't find window with name: '" << name << "'. Do nothing"); + CV_NOT_FOUND_DEPRECATION; + } + else + { + CV_LOG_WARNING(NULL, "No UI backends available. Use OPENCV_LOG_LEVEL=DEBUG for investigation"); + } + return -1; +#else switch(prop_id) { case CV_WND_PROP_FULLSCREEN: @@ -361,13 +396,13 @@ CV_IMPL double cvGetWindowProperty(const char* name, int prop_id) default: return -1; } +#endif } cv::Rect cvGetWindowImageRect(const char* name) { CV_TRACE_FUNCTION(); - if (!name) - return cv::Rect(-1, -1, -1, -1); + CV_Assert(name); { auto window = findWindow_(name); @@ -377,6 +412,20 @@ cv::Rect cvGetWindowImageRect(const char* name) } } +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) + auto backend = getCurrentUIBackend(); + if (backend) + { + CV_LOG_WARNING(NULL, "Can't find window with name: '" << name << "'. Do nothing"); + CV_NOT_FOUND_DEPRECATION; + } + else + { + CV_LOG_WARNING(NULL, "No UI backends available. Use OPENCV_LOG_LEVEL=DEBUG for investigation"); + } + return Rect(-1, -1, -1, -1); +#else + #if defined (HAVE_QT) return cvGetWindowRect_QT(name); #elif defined(HAVE_WIN32UI) @@ -386,8 +435,10 @@ cv::Rect cvGetWindowImageRect(const char* name) #elif defined (HAVE_COCOA) return cvGetWindowRect_COCOA(name); #else - return cv::Rect(-1, -1, -1, -1); + return Rect(-1, -1, -1, -1); #endif + +#endif } cv::Rect cv::getWindowImageRect(const String& winname) @@ -483,7 +534,21 @@ void cv::resizeWindow( const String& winname, int width, int height ) } } +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) + auto backend = getCurrentUIBackend(); + if (backend) + { + CV_LOG_WARNING(NULL, "Can't find window with name: '" << winname << "'. Do nothing"); + CV_NOT_FOUND_DEPRECATION; + } + else + { + CV_LOG_WARNING(NULL, "No UI backends available. Use OPENCV_LOG_LEVEL=DEBUG for investigation"); + } + return; +#else cvResizeWindow( winname.c_str(), width, height ); +#endif } void cv::resizeWindow(const String& winname, const cv::Size& size) @@ -504,7 +569,21 @@ void cv::moveWindow( const String& winname, int x, int y ) } } +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) + auto backend = getCurrentUIBackend(); + if (backend) + { + CV_LOG_WARNING(NULL, "Can't find window with name: '" << winname << "'. Do nothing"); + CV_NOT_FOUND_DEPRECATION; + } + else + { + CV_LOG_WARNING(NULL, "No UI backends available. Use OPENCV_LOG_LEVEL=DEBUG for investigation"); + } + return; +#else cvMoveWindow( winname.c_str(), x, y ); +#endif } void cv::setWindowProperty(const String& winname, int prop_id, double prop_value) @@ -616,8 +695,22 @@ int cv::createTrackbar(const String& trackbarName, const String& winName, } } +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) + auto backend = getCurrentUIBackend(); + if (backend) + { + CV_LOG_WARNING(NULL, "Can't find window with name: '" << winName << "'. Do nothing"); + CV_NOT_FOUND_DEPRECATION; + } + else + { + CV_LOG_WARNING(NULL, "No UI backends available. Use OPENCV_LOG_LEVEL=DEBUG for investigation"); + } + return 0; +#else return cvCreateTrackbar2(trackbarName.c_str(), winName.c_str(), value, count, callback, userdata); +#endif } void cv::setTrackbarPos( const String& trackbarName, const String& winName, int value ) @@ -635,7 +728,21 @@ void cv::setTrackbarPos( const String& trackbarName, const String& winName, int } } +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) + auto backend = getCurrentUIBackend(); + if (backend) + { + CV_LOG_WARNING(NULL, "Can't find window with name: '" << winName << "'. Do nothing"); + CV_NOT_FOUND_DEPRECATION; + } + else + { + CV_LOG_WARNING(NULL, "No UI backends available. Use OPENCV_LOG_LEVEL=DEBUG for investigation"); + } + return; +#else cvSetTrackbarPos(trackbarName.c_str(), winName.c_str(), value ); +#endif } void cv::setTrackbarMax(const String& trackbarName, const String& winName, int maxval) @@ -655,7 +762,21 @@ void cv::setTrackbarMax(const String& trackbarName, const String& winName, int m } } +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) + auto backend = getCurrentUIBackend(); + if (backend) + { + CV_LOG_WARNING(NULL, "Can't find window with name: '" << winName << "'. Do nothing"); + CV_NOT_FOUND_DEPRECATION; + } + else + { + CV_LOG_WARNING(NULL, "No UI backends available. Use OPENCV_LOG_LEVEL=DEBUG for investigation"); + } + return; +#else cvSetTrackbarMax(trackbarName.c_str(), winName.c_str(), maxval); +#endif } void cv::setTrackbarMin(const String& trackbarName, const String& winName, int minval) @@ -675,7 +796,21 @@ void cv::setTrackbarMin(const String& trackbarName, const String& winName, int m } } +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) + auto backend = getCurrentUIBackend(); + if (backend) + { + CV_LOG_WARNING(NULL, "Can't find window with name: '" << winName << "'. Do nothing"); + CV_NOT_FOUND_DEPRECATION; + } + else + { + CV_LOG_WARNING(NULL, "No UI backends available. Use OPENCV_LOG_LEVEL=DEBUG for investigation"); + } + return; +#else cvSetTrackbarMin(trackbarName.c_str(), winName.c_str(), minval); +#endif } int cv::getTrackbarPos( const String& trackbarName, const String& winName ) @@ -693,7 +828,21 @@ int cv::getTrackbarPos( const String& trackbarName, const String& winName ) } } +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) + auto backend = getCurrentUIBackend(); + if (backend) + { + CV_LOG_WARNING(NULL, "Can't find window with name: '" << winName << "'. Do nothing"); + CV_NOT_FOUND_DEPRECATION; + } + else + { + CV_LOG_WARNING(NULL, "No UI backends available. Use OPENCV_LOG_LEVEL=DEBUG for investigation"); + } + return -1; +#else return cvGetTrackbarPos(trackbarName.c_str(), winName.c_str()); +#endif } void cv::setMouseCallback( const String& windowName, MouseCallback onMouse, void* param) @@ -709,7 +858,21 @@ void cv::setMouseCallback( const String& windowName, MouseCallback onMouse, void } } +#if defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND) && defined(ENABLE_PLUGINS) + auto backend = getCurrentUIBackend(); + if (backend) + { + CV_LOG_WARNING(NULL, "Can't find window with name: '" << windowName << "'. Do nothing"); + CV_NOT_FOUND_DEPRECATION; + } + else + { + CV_LOG_WARNING(NULL, "No UI backends available. Use OPENCV_LOG_LEVEL=DEBUG for investigation"); + } + return; +#else cvSetMouseCallback(windowName.c_str(), onMouse, param); +#endif } int cv::getMouseWheelDelta( int flags ) From 80238880e66c2210daa5d67b2dff60ac4a599c8c Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 9 Jun 2021 09:04:29 +0000 Subject: [PATCH 3/3] highgui(gtk): fix initialization order of global objects --- modules/highgui/src/window_gtk.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index a07c3ad5cc..efa3fbd96f 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -2331,6 +2331,11 @@ public: class GTKBackendUI : public UIBackend { public: + GTKBackendUI() + { + // NB: avoid static initialization order fiasco + (void)getGTKWindows(); + } ~GTKBackendUI() CV_OVERRIDE { destroyAllWindows();