Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

highgui: wayland: fix to pass highgui test #25551

Merged
merged 6 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions modules/highgui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ list(REMOVE_ITEM highgui_ext_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${n
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "")

if(WITH_WAYLAND AND HAVE_WAYLAND)
# To optimize Mat to XRGB8888 conversion.
ocv_add_dispatched_file(write_mat_to_xrgb8888 SSE4_1 AVX2 NEON)

set(OPENCV_HIGHGUI_BUILTIN_BACKEND "Wayland")
add_definitions(-DHAVE_WAYLAND)

Expand All @@ -63,6 +66,7 @@ if(WITH_WAYLAND AND HAVE_WAYLAND)

list(APPEND highgui_srcs
${CMAKE_CURRENT_LIST_DIR}/src/window_wayland.cpp
${CMAKE_CURRENT_LIST_DIR}/src/write_mat_to_xrgb8888.dispatch.cpp
${WAYLAND_PROTOCOL_SOURCES}
)
list(APPEND HIGHGUI_LIBRARIES "${WAYLAND_CLIENT_LINK_LIBRARIES};${WAYLAND_CURSOR_LINK_LIBRARIES};${XKBCOMMON_LINK_LIBRARIES}")
Expand Down
13 changes: 13 additions & 0 deletions modules/highgui/include/opencv2/highgui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,11 @@ for image display). **waitKey(25)** will display a frame and wait approximately
press (suitable for displaying a video frame-by-frame). To remove the window, use cv::destroyWindow.

@note [__Windows Backend Only__] Pressing Ctrl+C will copy the image to the clipboard. Pressing Ctrl+S will show a dialog to save the image.
@note [__Wayland Backend Only__] Supoorting format is extended.
- If the image is 8-bit signed, the pixels are biased by 128. That is, the
value range [-128,127] is mapped to [0,255].
- If the image is 16-bit signed, the pixels are divided by 256 and biased by 128. That is, the
value range [-32768,32767] is mapped to [0,255].

@param winname Name of the window.
@param mat Image to be shown.
Expand Down Expand Up @@ -394,6 +399,8 @@ CV_EXPORTS_W void resizeWindow(const String& winname, const cv::Size& size);
@param winname Name of the window.
@param x The new x-coordinate of the window.
@param y The new y-coordinate of the window.

@note [__Wayland Backend Only__] This function is not supported by the wayland protocol limitation.
asmorkalov marked this conversation as resolved.
Show resolved Hide resolved
*/
CV_EXPORTS_W void moveWindow(const String& winname, int x, int y);

Expand All @@ -404,6 +411,8 @@ The function setWindowProperty enables changing properties of a window.
@param winname Name of the window.
@param prop_id Window property to edit. The supported operation flags are: (cv::WindowPropertyFlags)
@param prop_value New value of the window property. The supported flags are: (cv::WindowFlags)

@note [__Wayland Backend Only__] This function is not supported.
*/
CV_EXPORTS_W void setWindowProperty(const String& winname, int prop_id, double prop_value);

Expand All @@ -421,6 +430,8 @@ The function getWindowProperty returns properties of a window.
@param prop_id Window property to retrieve. The following operation flags are available: (cv::WindowPropertyFlags)

@sa setWindowProperty

@note [__Wayland Backend Only__] This function is not supported.
*/
CV_EXPORTS_W double getWindowProperty(const String& winname, int prop_id);

Expand All @@ -431,6 +442,8 @@ The function getWindowImageRect returns the client screen coordinates, width and
@param winname Name of the window.

@sa resizeWindow moveWindow

@note [__Wayland Backend Only__] This function is not supported by the wayland protocol limitation.
*/
CV_EXPORTS_W Rect getWindowImageRect(const String& winname);

Expand Down
1 change: 1 addition & 0 deletions modules/highgui/src/precomp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ void cvSetModeWindow_WinRT(const char* name, double prop_value);
CvRect cvGetWindowRect_W32(const char* name);
CvRect cvGetWindowRect_GTK(const char* name);
CvRect cvGetWindowRect_COCOA(const char* name);
CvRect cvGetWindowRect_WAYLAND(const char* name);

double cvGetModeWindow_W32(const char* name);
double cvGetModeWindow_GTK(const char* name);
Expand Down
2 changes: 2 additions & 0 deletions modules/highgui/src/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,8 @@ cv::Rect cv::getWindowImageRect(const String& winname)
return cvGetWindowRect_GTK(winname.c_str());
#elif defined (HAVE_COCOA)
return cvGetWindowRect_COCOA(winname.c_str());
#elif defined (HAVE_WAYLAND)
return cvGetWindowRect_WAYLAND(winname.c_str());
#else
return Rect(-1, -1, -1, -1);
#endif
Expand Down
80 changes: 45 additions & 35 deletions modules/highgui/src/window_wayland.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/core/utils/logger.hpp"
#include "opencv2/core/hal/intrin.hpp"

#include "write_mat_to_xrgb8888.hpp"

/* */
/* OpenCV highgui internals */
Expand Down Expand Up @@ -69,6 +72,7 @@ class cv_wl_core;
using std::weak_ptr;
using std::shared_ptr;
using namespace cv::Error;
using namespace cv::impl;
namespace ch = std::chrono;

#define throw_system_error(errmsg, errnum) \
Expand All @@ -85,22 +89,6 @@ static int xkb_keysym_to_ascii(xkb_keysym_t keysym) {
}


asmorkalov marked this conversation as resolved.
Show resolved Hide resolved
static void draw_xrgb8888(void *d, uint8_t a, uint8_t r, uint8_t g, uint8_t b) {
*((uint32_t *) d) = ((a << 24) | (r << 16) | (g << 8) | b);
}

static void write_mat_to_xrgb8888(cv::Mat const &img, void *data) {
CV_Assert(data != nullptr);
CV_Assert(img.isContinuous());

for (int y = 0; y < img.rows; y++) {
for (int x = 0; x < img.cols; x++) {
auto p = img.at<cv::Vec3b>(y, x);
draw_xrgb8888((char *) data + (y * img.cols + x) * 4, 0x00, p[2], p[1], p[0]);
}
}
}

class epoller {
public:
epoller() : epoll_fd_(epoll_create1(EPOLL_CLOEXEC)) {
Expand Down Expand Up @@ -232,10 +220,10 @@ class cv_wl_mouse {
&handle_pointer_axis, &handle_pointer_frame,
&handle_pointer_axis_source, &handle_pointer_axis_stop,
&handle_pointer_axis_discrete,
#if WL_POINTER_AXIS_VALUE120_SINCE_VERSION >= 8
#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION
&handle_axis_value120,
#endif
#if WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION >= 9
#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION
&handle_axis_relative_direction,
#endif
};
Expand Down Expand Up @@ -284,7 +272,7 @@ class cv_wl_mouse {
CV_UNUSED(discrete);
}

#if WL_POINTER_AXIS_VALUE120_SINCE_VERSION >= 8
#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION
static void
handle_axis_value120(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t value120) {
CV_UNUSED(data);
Expand All @@ -294,7 +282,7 @@ class cv_wl_mouse {
}
#endif

#if WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION >= 9
#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION
static void
handle_axis_relative_direction(void *data, struct wl_pointer *wl_pointer, uint32_t axis, uint32_t direction) {
CV_UNUSED(data);
Expand Down Expand Up @@ -686,7 +674,7 @@ class cv_wl_window {

void show_image(cv::Mat const &image);

void create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change, void *userdata);
int create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change, void *userdata);

weak_ptr<cv_wl_trackbar> get_trackbar(std::string const &) const;

Expand Down Expand Up @@ -723,10 +711,10 @@ class cv_wl_window {
struct xdg_toplevel *xdg_toplevel_;
struct xdg_toplevel_listener xdgtop_listener_{
&handle_toplevel_configure, &handle_toplevel_close,
#if XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION >= 4
#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION
&handle_toplevel_configure_bounds,
#endif
#if XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION >= 5
#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
&handle_toplevel_wm_capabilities,
#endif
};
Expand Down Expand Up @@ -775,7 +763,7 @@ class cv_wl_window {

static void handle_toplevel_close(void *data, struct xdg_toplevel *surface);

#if XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION >= 4
#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION
static void
handle_toplevel_configure_bounds(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height)
{
Expand All @@ -786,7 +774,7 @@ class cv_wl_window {
}
#endif

#if XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION >= 5
#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
static void
handle_toplevel_wm_capabilities(void *data, struct xdg_toplevel *xdg_toplevel, struct wl_array *capabilities)
{
Expand Down Expand Up @@ -1527,13 +1515,7 @@ cv_wl_viewer::cv_wl_viewer(cv_wl_window *window, int flags)
}

void cv_wl_viewer::set_image(cv::Mat const &image) {
if (image.type() == CV_8UC1) {
cv::Mat bgr;
cv::cvtColor(image, bgr, CV_GRAY2BGR);
image_ = bgr.clone();
} else {
image_ = image.clone();
}
image_ = image.clone();
image_changed_ = true;
}

Expand Down Expand Up @@ -1642,6 +1624,11 @@ cv_wl_trackbar::cv_wl_trackbar(cv_wl_window *window, std::string name,
on_change_.value = value;
on_change_.data = data;
on_change_.callback = on_change;

// initilize slider_.value if value is not nullptr.
if (value != nullptr){
set_pos(*value);
}
}

std::string const &cv_wl_trackbar::name() const {
Expand All @@ -1657,6 +1644,12 @@ void cv_wl_trackbar::set_pos(int value) {
slider_.value = value;
slider_moved_ = true;
window_->show();

// Update user-ptr value and call on_change() function if cv_wl_trackbar::draw() is not called.
if(slider_moved_) {
on_change_.update(slider_.value);
on_change_.call(slider_.value);
}
}
}

Expand All @@ -1666,6 +1659,12 @@ void cv_wl_trackbar::set_max(int maxval) {
slider_.value = maxval;
slider_moved_ = true;
window_->show();

// Update user-ptr and call on_change() function if cv_wl_trackbar::draw() is not called.
if(slider_moved_) {
on_change_.update(slider_.value);
on_change_.call(slider_.value);
}
}
}

Expand Down Expand Up @@ -1836,8 +1835,9 @@ void cv_wl_window::show_image(cv::Mat const &image) {
this->show();
}

void cv_wl_window::create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change,
int cv_wl_window::create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change,
void *userdata) {
int ret = 0;
auto exists = this->get_trackbar(name).lock();
if (!exists) {
auto trackbar =
Expand All @@ -1846,7 +1846,9 @@ void cv_wl_window::create_trackbar(std::string const &name, int *value, int coun
);
widgets_.emplace_back(trackbar);
widget_geometries_.emplace_back(0, 0, 0, 0);
ret = 1;
}
return ret;
}

weak_ptr<cv_wl_trackbar> cv_wl_window::get_trackbar(std::string const &trackbar_name) const {
Expand Down Expand Up @@ -2402,6 +2404,13 @@ CV_IMPL void cvResizeWindow(const char *name, int width, int height) {
throw_system_error("Could not get window name", errno)
}

CvRect cvGetWindowRect_WAYLAND(const char* name)
{
CV_UNUSED(name);
CV_LOG_ONCE_WARNING(nullptr, "Function not implemented: User cannot get window rect in Wayland");
return cvRect(-1, -1, -1, -1);
}

CV_IMPL int cvCreateTrackbar(const char *name_bar, const char *window_name, int *value, int count,
CvTrackbarCallback on_change) {
CV_UNUSED(name_bar);
Expand All @@ -2416,10 +2425,11 @@ CV_IMPL int cvCreateTrackbar(const char *name_bar, const char *window_name, int

CV_IMPL int cvCreateTrackbar2(const char *trackbar_name, const char *window_name, int *val, int count,
CvTrackbarCallback2 on_notify, void *userdata) {
int ret = 0;
if (auto window = CvWlCore::getInstance().get_window(window_name))
window->create_trackbar(trackbar_name, val, count, on_notify, userdata);
ret = window->create_trackbar(trackbar_name, val, count, on_notify, userdata);

return 0;
return ret;
}

CV_IMPL int cvGetTrackbarPos(const char *trackbar_name, const char *window_name) {
Expand Down
66 changes: 66 additions & 0 deletions modules/highgui/src/write_mat_to_xrgb8888.dispatch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// 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.

#include "precomp.hpp"

#include "write_mat_to_xrgb8888.hpp"
#include "write_mat_to_xrgb8888.simd.hpp"
#include "write_mat_to_xrgb8888.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content


namespace cv {
namespace impl {
void write_mat_to_xrgb8888(cv::Mat const &img_, void *data)
{
cv::Mat img;

// The supported Mat depth is according to imshow() specification.
const int depth = CV_MAT_DEPTH(img_.type());
const int ncn = img_.channels();
const int mtype = CV_MAKE_TYPE(CV_8U, ncn);

CV_CheckType(img_.type(),
( (ncn == 1) || (ncn == 3) || (ncn == 4)),
"Unsupported channels, please convert to 1, 3 or 4 channels"
);

CV_CheckType(img_.type(),
( (depth == CV_8U) || (depth == CV_8S) ||
(depth == CV_16U) || (depth == CV_16S) ||
(depth == CV_32F) || (depth == CV_64F) ),
"Unsupported depth, please convert to CV_8U"
);

switch(CV_MAT_DEPTH(depth))
{
case CV_8U:
img = img_; // do nothing.
break;
case CV_8S:
// [-128,127] -> [0,255]
img_.convertTo(img, mtype, 1.0, 128);
break;
case CV_16U:
// [0,65535] -> [0,255]
img_.convertTo(img, mtype, 1.0/255. );
break;
case CV_16S:
// [-32768,32767] -> [0,255]
img_.convertTo(img, mtype, 1.0/255. , 128);
break;
case CV_32F:
case CV_64F:
// [0, 1] -> [0,255]
img_.convertTo(img, mtype, 255.);
break;
default:
// it cannot be reachable.
break;
}

CV_CPU_DISPATCH(write_mat_to_xrgb8888, (img, data), CV_CPU_DISPATCH_MODES_ALL);
}

} // namespace impl
} // namespace cv
10 changes: 10 additions & 0 deletions modules/highgui/src/write_mat_to_xrgb8888.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// 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.

namespace cv {
namespace impl{
void write_mat_to_xrgb8888(cv::Mat const &img, void *data);

} // namespace impl
} // namespace cv