From 327109f327f1521c7d7f900914fb0fa999a525e6 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 4 Jun 2021 17:15:07 +0000 Subject: [PATCH] highgui: update backends handling, fix WITH_OPENGL=ON build --- modules/highgui/CMakeLists.txt | 56 +++++++++++-------- modules/highgui/cmake/detect_gtk.cmake | 13 ++++- modules/highgui/cmake/init.cmake | 27 +++++++++ modules/highgui/misc/plugins/build_plugins.sh | 11 ++-- .../misc/plugins/plugin_gtk/CMakeLists.txt | 20 +++++-- .../plugins/plugin_gtk/Dockerfile-ubuntu-gtk2 | 7 +++ .../highgui/misc/plugins/plugin_gtk/build.sh | 14 ++++- modules/highgui/src/backend.cpp | 3 +- modules/highgui/src/registry.impl.hpp | 1 + modules/highgui/src/window_gtk.cpp | 16 ++++-- 10 files changed, 127 insertions(+), 41 deletions(-) diff --git a/modules/highgui/CMakeLists.txt b/modules/highgui/CMakeLists.txt index 9b68b4672e..a0f444fd52 100644 --- a/modules/highgui/CMakeLists.txt +++ b/modules/highgui/CMakeLists.txt @@ -1,26 +1,5 @@ set(the_description "High-level GUI") -set(ENABLE_PLUGINS_DEFAULT ON) -if(EMSCRIPTEN OR IOS OR WINRT) - set(ENABLE_PLUGINS_DEFAULT OFF) -endif() -set(HIGHGUI_PLUGIN_LIST "" CACHE STRING "List of GUI backends to be compiled as plugins (gtk, gtk2/gtk3, qt, win32 or special value 'all')") -set(HIGHGUI_ENABLE_PLUGINS "${ENABLE_PLUGINS_DEFAULT}" CACHE BOOL "Allow building and using of GUI plugins") -mark_as_advanced(HIGHGUI_PLUGIN_LIST HIGHGUI_ENABLE_PLUGINS) - -string(REPLACE "," ";" HIGHGUI_PLUGIN_LIST "${HIGHGUI_PLUGIN_LIST}") # support comma-separated list (,) too -if(NOT HIGHGUI_ENABLE_PLUGINS) - if(HIGHGUI_PLUGIN_LIST) - message(WARNING "HighGUI: plugins are disabled through HIGHGUI_ENABLE_PLUGINS, so HIGHGUI_PLUGIN_LIST='${HIGHGUI_PLUGIN_LIST}' is ignored") - set(HIGHGUI_PLUGIN_LIST "") - endif() -else() - # Make virtual plugins target - if(NOT TARGET opencv_highgui_plugins) - add_custom_target(opencv_highgui_plugins ALL) - endif() -endif() - if(ANDROID) ocv_add_module(highgui opencv_imgproc opencv_imgcodecs OPTIONAL opencv_videoio WRAP python) else() @@ -68,7 +47,10 @@ file(GLOB highgui_ext_hdrs # Removing WinRT API headers by default list(REMOVE_ITEM highgui_ext_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/highgui_winrt.hpp") +set(OPENCV_HIGHGUI_BUILTIN_BACKEND "") + if(HAVE_QT5) + set(OPENCV_HIGHGUI_BUILTIN_BACKEND "QT5") add_definitions(-DHAVE_QT) # "Automoc" doesn't work properly with opencv_world build, use QT5_WRAP_CPP() directly @@ -96,8 +78,8 @@ if(HAVE_QT5) include_directories(${Qt5OpenGL_INCLUDE_DIRS}) list(APPEND HIGHGUI_LIBRARIES ${Qt5OpenGL_LIBRARIES}) endif() - elseif(HAVE_QT) + set(OPENCV_HIGHGUI_BUILTIN_BACKEND "QT4") add_definitions(-DHAVE_QT) if(HAVE_QT_OPENGL) add_definitions(-DHAVE_QT_OPENGL) @@ -115,6 +97,7 @@ elseif(HAVE_QT) set_source_files_properties(${_RCC_OUTFILES} PROPERTIES COMPILE_FLAGS -Wno-missing-declarations) endif() elseif(WINRT) + set(OPENCV_HIGHGUI_BUILTIN_BACKEND "WINRT") if(NOT WINRT_8_0) # Dependencies used by the implementation referenced # below are not available on WinRT 8.0. @@ -149,11 +132,13 @@ elseif(WINRT) message(STATUS " ${name}: Leaving '${HIGHGUI_LIBRARIES}'") endif() elseif(HAVE_WIN32UI) + set(OPENCV_HIGHGUI_BUILTIN_BACKEND "WIN32UI") list(APPEND highgui_srcs ${CMAKE_CURRENT_LIST_DIR}/src/window_w32.cpp) if(OpenCV_ARCH STREQUAL "ARM64") list(APPEND HIGHGUI_LIBRARIES "comdlg32" "advapi32") endif() elseif(HAVE_COCOA) + set(OPENCV_HIGHGUI_BUILTIN_BACKEND "COCOA") add_definitions(-DHAVE_COCOA) list(APPEND highgui_srcs ${CMAKE_CURRENT_LIST_DIR}/src/window_cocoa.mm) list(APPEND HIGHGUI_LIBRARIES "-framework Cocoa") @@ -170,16 +155,31 @@ if(TARGET ocv.3rdparty.gtk3 OR TARGET ocv.3rdparty.gtk2) AND NOT "gtk" IN_LIST HIGHGUI_PLUGIN_LIST AND NOT "gtk2" IN_LIST HIGHGUI_PLUGIN_LIST AND NOT "gtk3" IN_LIST HIGHGUI_PLUGIN_LIST + AND NOT OPENCV_HIGHGUI_BUILTIN_BACKEND ) + if(__gtk_dependency STREQUAL "ocv.3rdparty.gtk3") + set(OPENCV_HIGHGUI_BUILTIN_BACKEND "GTK3") + elseif(__gtk_dependency STREQUAL "ocv.3rdparty.gtk2") + set(OPENCV_HIGHGUI_BUILTIN_BACKEND "GTK2") + else() + set(OPENCV_HIGHGUI_BUILTIN_BACKEND "GTK") + endif() list(APPEND highgui_srcs ${CMAKE_CURRENT_LIST_DIR}/src/window_gtk.cpp) list(APPEND tgts ${__gtk_dependency}) if(TARGET ocv.3rdparty.gthread) list(APPEND tgts ocv.3rdparty.gthread) endif() if(TARGET ocv.3rdparty.gtkglext + AND __gtk_dependency STREQUAL "ocv.3rdparty.gtk2" AND NOT OPENCV_GTK_DISABLE_GTKGLEXT ) list(APPEND tgts ocv.3rdparty.gtkglext) + if(TARGET ocv.3rdparty.gtk_opengl + AND __gtk_dependency STREQUAL "ocv.3rdparty.gtk2" + AND NOT OPENCV_GTK_DISABLE_OPENGL + ) + list(APPEND tgts ocv.3rdparty.gtk_opengl) + endif() endif() elseif("gtk" IN_LIST HIGHGUI_PLUGIN_LIST) ocv_create_builtin_highgui_plugin(opencv_highgui_gtk ${__gtk_dependency} "window_gtk.cpp") @@ -211,6 +211,11 @@ if(TARGET ocv.3rdparty.gtk3 OR TARGET ocv.3rdparty.gtk2) endif() endif() +if(NOT OPENCV_HIGHGUI_BUILTIN_BACKEND) + set(OPENCV_HIGHGUI_BUILTIN_BACKEND "NONE") +endif() +message(STATUS "highgui: using builtin backend: ${OPENCV_HIGHGUI_BUILTIN_BACKEND}") # FIXIT: propagate to root CMake + if(TRUE) # these variables are set by 'ocv_append_build_options(HIGHGUI ...)' foreach(P ${HIGHGUI_INCLUDE_DIRS}) @@ -271,3 +276,10 @@ if(HIGHGUI_ENABLE_PLUGINS) endif() ocv_target_link_libraries(${the_module} LINK_PRIVATE ${tgts}) + +# generate module configuration +set(CONFIG_STR "// Auto-generated file +#define OPENCV_HIGHGUI_BUILTIN_BACKEND_STR \"${OPENCV_HIGHGUI_BUILTIN_BACKEND}\" +") + +ocv_update_file("${CMAKE_CURRENT_BINARY_DIR}/opencv_highgui_config.hpp" "${CONFIG_STR}") diff --git a/modules/highgui/cmake/detect_gtk.cmake b/modules/highgui/cmake/detect_gtk.cmake index 1f91986020..cdc054fad0 100644 --- a/modules/highgui/cmake/detect_gtk.cmake +++ b/modules/highgui/cmake/detect_gtk.cmake @@ -1,5 +1,5 @@ # --- GTK --- -ocv_clear_vars(HAVE_GTK HAVE_GTK3 HAVE_GTHREAD HAVE_GTKGLEXT) +ocv_clear_vars(HAVE_GTK HAVE_GTK2 HAVE_GTK3 HAVE_GTHREAD HAVE_GTKGLEXT) if(WITH_GTK) if(NOT WITH_GTK_2_X) ocv_check_modules(GTK3 gtk+-3.0) @@ -32,7 +32,7 @@ if(WITH_GTK) set(HAVE_GTHREAD "${HAVE_GTHREAD}" PARENT_SCOPE) # informational set(GTHREAD_VERSION "${GTHREAD_VERSION}" PARENT_SCOPE) # informational endif() - if(WITH_OPENGL AND NOT HAVE_GTK3) + if((WITH_OPENGL OR HAVE_OPENGL) AND HAVE_GTK2) ocv_check_modules(GTKGLEXT gtkglext-1.0) if(HAVE_GTKGLEXT) ocv_add_external_target(gtkglext "${GTKGLEXT_INCLUDE_DIRS}" "${GTKGLEXT_LIBRARIES}" "HAVE_GTKGLEXT") @@ -44,4 +44,13 @@ elseif(HAVE_GTK) ocv_add_external_target(gtk "${GTK_INCLUDE_DIRS}" "${GTK_LIBRARIES}" "${GTK_DEFINES};HAVE_GTK") endif() +if(WITH_OPENGL AND HAVE_GTKGLEXT) + find_package(OpenGL QUIET) + if(OPENGL_FOUND) + set(HAVE_OPENGL TRUE) + #set(HAVE_OPENGL ${HAVE_OPENGL} PARENT_SCOPE) + ocv_add_external_target(gtk_opengl "${OPENGL_INCLUDE_DIRS}" "${OPENGL_LIBRARIES}" "HAVE_OPENGL") + endif() +endif() + set(HAVE_GTK ${HAVE_GTK} PARENT_SCOPE) diff --git a/modules/highgui/cmake/init.cmake b/modules/highgui/cmake/init.cmake index 1a115f22ed..3b766b3758 100644 --- a/modules/highgui/cmake/init.cmake +++ b/modules/highgui/cmake/init.cmake @@ -1,3 +1,30 @@ +if(PROJECT_NAME STREQUAL "OpenCV") + set(ENABLE_PLUGINS_DEFAULT ON) + if(EMSCRIPTEN OR IOS OR WINRT) + set(ENABLE_PLUGINS_DEFAULT OFF) + endif() + set(HIGHGUI_PLUGIN_LIST "" CACHE STRING "List of GUI backends to be compiled as plugins (gtk, gtk2/gtk3, qt, win32 or special value 'all')") + set(HIGHGUI_ENABLE_PLUGINS "${ENABLE_PLUGINS_DEFAULT}" CACHE BOOL "Allow building and using of GUI plugins") + mark_as_advanced(HIGHGUI_PLUGIN_LIST HIGHGUI_ENABLE_PLUGINS) + + string(REPLACE "," ";" HIGHGUI_PLUGIN_LIST "${HIGHGUI_PLUGIN_LIST}") # support comma-separated list (,) too + if(NOT HIGHGUI_ENABLE_PLUGINS) + if(HIGHGUI_PLUGIN_LIST) + message(WARNING "HighGUI: plugins are disabled through HIGHGUI_ENABLE_PLUGINS, so HIGHGUI_PLUGIN_LIST='${HIGHGUI_PLUGIN_LIST}' is ignored") + set(HIGHGUI_PLUGIN_LIST "") + endif() + else() + # Make virtual plugins target + if(NOT TARGET opencv_highgui_plugins) + add_custom_target(opencv_highgui_plugins ALL) + endif() + endif() +endif() + +# +# Detect available dependencies +# + include(FindPkgConfig) # FIXIT: stop using PARENT_SCOPE in dependencies diff --git a/modules/highgui/misc/plugins/build_plugins.sh b/modules/highgui/misc/plugins/build_plugins.sh index a27f4a0eca..0018eef3ba 100755 --- a/modules/highgui/misc/plugins/build_plugins.sh +++ b/modules/highgui/misc/plugins/build_plugins.sh @@ -11,7 +11,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" OCV="$( cd "${DIR}/../../../.." >/dev/null 2>&1 && pwd )" mkdir -p "${1}" # Docker creates non-existed mounts with 'root' owner, lets ensure that dir exists under the current user to avoid "Permission denied" problem DST="$( cd "$1" >/dev/null 2>&1 && pwd )" -CFG=$2 +CFG=${2:-Release} do_build() { @@ -40,30 +40,33 @@ docker run \ -e CFG=$CFG \ --user $(id -u):$(id -g) \ $TAG \ - $@ + "$@" } build_gtk2_ubuntu() { VER=$1 +shift 1 TAG=opencv_highgui_ubuntu_gtk2_builder:${VER} do_build $TAG "${DIR}/plugin_gtk" Dockerfile-ubuntu-gtk2 --build-arg VER=${VER} -do_run $TAG /opencv/modules/highgui/misc/plugins/plugin_gtk/build.sh /dst gtk2_ubuntu${VER} ${CFG} +do_run $TAG /opencv/modules/highgui/misc/plugins/plugin_gtk/build.sh /dst gtk2_ubuntu${VER} ${CFG} "$@" } build_gtk3_ubuntu() { VER=$1 +shift 1 TAG=opencv_highgui_ubuntu_gtk3_builder:${VER} do_build $TAG "${DIR}/plugin_gtk" Dockerfile-ubuntu-gtk3 --build-arg VER=${VER} -do_run $TAG /opencv/modules/highgui/misc/plugins/plugin_gtk/build.sh /dst gtk3_ubuntu${VER} ${CFG} +do_run $TAG /opencv/modules/highgui/misc/plugins/plugin_gtk/build.sh /dst gtk3_ubuntu${VER} ${CFG} "$@" } echo "OpenCV: ${OCV}" echo "Destination: ${DST}" build_gtk2_ubuntu 16.04 +build_gtk2_ubuntu 16.04 -DOPENCV_PLUGIN_NAME=opencv_highgui_gtk2-opengl_ubuntu16.04 -DWITH_OPENGL=ON -DWITH_GTK_2_X=ON build_gtk2_ubuntu 18.04 build_gtk3_ubuntu 18.04 build_gtk3_ubuntu 20.04 diff --git a/modules/highgui/misc/plugins/plugin_gtk/CMakeLists.txt b/modules/highgui/misc/plugins/plugin_gtk/CMakeLists.txt index 22462900f1..6a2da0c9c3 100644 --- a/modules/highgui/misc/plugins/plugin_gtk/CMakeLists.txt +++ b/modules/highgui/misc/plugins/plugin_gtk/CMakeLists.txt @@ -25,6 +25,21 @@ else() message(FATAL_ERROR "Missing dependency target for GTK libraries") endif() ocv_create_plugin(highgui "opencv_highgui_gtk" "${__deps}" "GTK" "src/window_gtk.cpp") +if(WITH_OPENGL) + if(HAVE_GTK2 + AND TARGET ocv.3rdparty.gtkglext + AND TARGET ocv.3rdparty.gtk_opengl + AND NOT OPENCV_GTK_DISABLE_GTKGLEXT + AND NOT OPENCV_GTK_DISABLE_OPENGL + ) + message(STATUS "OpenGL: YES") + target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE + ocv.3rdparty.gtkglext ocv.3rdparty.gtk_opengl + ) + else() + message(WARNING "OpenGL dependencies are not available!") + endif() +endif() if(HAVE_GTK3) message(STATUS "GTK3+: ver ${GTK3_VERSION}") @@ -41,8 +56,3 @@ if(HAVE_GTHREAD) else() message(STATUS "GThread : NO") endif() -if(HAVE_GTKGLEXT) - message(STATUS "GtkGlExt: YES (ver ${GTKGLEXT_VERSION})") -else() - message(STATUS "GtkGlExt: NO") -endif() diff --git a/modules/highgui/misc/plugins/plugin_gtk/Dockerfile-ubuntu-gtk2 b/modules/highgui/misc/plugins/plugin_gtk/Dockerfile-ubuntu-gtk2 index 81836cb384..fefa0ba339 100644 --- a/modules/highgui/misc/plugins/plugin_gtk/Dockerfile-ubuntu-gtk2 +++ b/modules/highgui/misc/plugins/plugin_gtk/Dockerfile-ubuntu-gtk2 @@ -18,4 +18,11 @@ RUN \ && \ rm -rf /var/lib/apt/lists/* +RUN \ + apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + libgtkglext1-dev \ + && \ + rm -rf /var/lib/apt/lists/* + WORKDIR /tmp diff --git a/modules/highgui/misc/plugins/plugin_gtk/build.sh b/modules/highgui/misc/plugins/plugin_gtk/build.sh index 58048698db..4383016910 100755 --- a/modules/highgui/misc/plugins/plugin_gtk/build.sh +++ b/modules/highgui/misc/plugins/plugin_gtk/build.sh @@ -4,10 +4,18 @@ set -e DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +OPENCV_PLUGIN_DESTINATION=$1 +OPENCV_PLUGIN_NAME=opencv_highgui_$2 +CMAKE_BUILD_TYPE=${3:-Release} + +shift 3 || true + +set -x cmake -GNinja \ - -DOPENCV_PLUGIN_NAME=opencv_highgui_$2 \ - -DOPENCV_PLUGIN_DESTINATION=$1 \ - -DCMAKE_BUILD_TYPE=$3 \ + -DOPENCV_PLUGIN_NAME=${OPENCV_PLUGIN_NAME} \ + -DOPENCV_PLUGIN_DESTINATION=${OPENCV_PLUGIN_DESTINATION} \ + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \ + "$@" \ $DIR ninja -v diff --git a/modules/highgui/src/backend.cpp b/modules/highgui/src/backend.cpp index 4c0de0584e..7c241ea907 100644 --- a/modules/highgui/src/backend.cpp +++ b/modules/highgui/src/backend.cpp @@ -2,6 +2,7 @@ // 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 @@ -103,7 +104,7 @@ std::shared_ptr createUIBackend() } if (name.empty()) { - CV_LOG_DEBUG(NULL, "UI: fallback on builtin code"); + CV_LOG_DEBUG(NULL, "UI: fallback on builtin code: " OPENCV_HIGHGUI_BUILTIN_BACKEND_STR); } else { diff --git a/modules/highgui/src/registry.impl.hpp b/modules/highgui/src/registry.impl.hpp index a2e4dbea47..9c50986a69 100644 --- a/modules/highgui/src/registry.impl.hpp +++ b/modules/highgui/src/registry.impl.hpp @@ -162,6 +162,7 @@ public: const BackendInfo& info = enabledBackends[i]; os << info.name << '(' << info.priority << ')'; } + os << " + BUILTIN(" OPENCV_HIGHGUI_BUILTIN_BACKEND_STR ")"; return os.str(); } diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index f2d02d66b0..f7570f42c7 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -45,6 +45,14 @@ #if defined (HAVE_GTK) #include + +#if (GTK_MAJOR_VERSION == 3) && defined(HAVE_OPENGL) + #undef HAVE_OPENGL // no support with GTK3 +#endif +#if defined(HAVE_OPENGL) && !defined(HAVE_GTKGLEXT) + #undef HAVE_OPENGL // gtkglext is required +#endif + #include #include #include @@ -1187,7 +1195,7 @@ static std::shared_ptr namedWindow_(const std::string& name, int flags #ifdef HAVE_OPENGL if (window->useGl) - cvSetOpenGlContext(name); + cvSetOpenGlContext(name.c_str()); #endif return window_ptr; @@ -1205,7 +1213,7 @@ CV_IMPL void cvSetOpenGlContext(const char* name) CV_LOCK_MUTEX(); - CvWindow* window = icvFindWindowByName(name); + auto window = icvFindWindowByName(name); if (!window) CV_Error( CV_StsNullPtr, "NULL window" ); @@ -1225,7 +1233,7 @@ CV_IMPL void cvUpdateWindow(const char* name) CV_LOCK_MUTEX(); - CvWindow* window = icvFindWindowByName(name); + auto window = icvFindWindowByName(name); if (!window) return; @@ -1239,7 +1247,7 @@ CV_IMPL void cvSetOpenGlDrawCallback(const char* name, CvOpenGlDrawCallback call CV_LOCK_MUTEX(); - CvWindow* window = icvFindWindowByName(name); + auto window = icvFindWindowByName(name); if( !window ) return; -- 2.34.1