mirror of
https://github.com/opencv/opencv.git
synced 2024-11-27 20:50:25 +08:00
Merge pull request #25822 from mqcmd196:gtk3-gl-support
Support OpenGL GTK3 New API #25822 Fixes #20001 GSoC2024 Project ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
parent
e90935e81c
commit
4842043c6a
@ -1468,11 +1468,14 @@ if(WITH_GTK OR HAVE_GTK)
|
|||||||
else()
|
else()
|
||||||
status(" GTK+:" "NO")
|
status(" GTK+:" "NO")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(HAVE_GTK)
|
if(HAVE_GTK)
|
||||||
status( " GThread :" HAVE_GTHREAD THEN "YES (ver ${GTHREAD_VERSION})" ELSE NO)
|
status( " GThread :" HAVE_GTHREAD THEN "YES (ver ${GTHREAD_VERSION})" ELSE NO)
|
||||||
|
if(NOT HAVE_GTK3)
|
||||||
status( " GtkGlExt:" HAVE_GTKGLEXT THEN "YES (ver ${GTKGLEXT_VERSION})" ELSE NO)
|
status( " GtkGlExt:" HAVE_GTKGLEXT THEN "YES (ver ${GTKGLEXT_VERSION})" ELSE NO)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_FRAMEBUFFER OR HAVE_FRAMEBUFFER)
|
if(WITH_FRAMEBUFFER OR HAVE_FRAMEBUFFER)
|
||||||
status(" Framebuffer UI:" HAVE_FRAMEBUFFER THEN YES ELSE NO)
|
status(" Framebuffer UI:" HAVE_FRAMEBUFFER THEN YES ELSE NO)
|
||||||
|
@ -63,7 +63,7 @@ endif()
|
|||||||
ocv_update(OpenGL_GL_PREFERENCE LEGACY)
|
ocv_update(OpenGL_GL_PREFERENCE LEGACY)
|
||||||
ocv_clear_vars(HAVE_OPENGL HAVE_QT_OPENGL)
|
ocv_clear_vars(HAVE_OPENGL HAVE_QT_OPENGL)
|
||||||
if(WITH_OPENGL)
|
if(WITH_OPENGL)
|
||||||
if(WITH_WIN32UI OR (HAVE_QT AND QT_QTOPENGL_FOUND) OR HAVE_GTKGLEXT)
|
if(WITH_WIN32UI OR (HAVE_QT AND QT_QTOPENGL_FOUND) OR HAVE_GTK3 OR (HAVE_GTK AND NOT HAVE_GTK3 AND HAVE_GTKGLEXT))
|
||||||
find_package (OpenGL QUIET)
|
find_package (OpenGL QUIET)
|
||||||
if(OPENGL_FOUND)
|
if(OPENGL_FOUND)
|
||||||
set(HAVE_OPENGL TRUE)
|
set(HAVE_OPENGL TRUE)
|
||||||
|
@ -57,7 +57,7 @@ This section describes OpenGL interoperability.
|
|||||||
|
|
||||||
To enable OpenGL support, configure OpenCV using CMake with WITH_OPENGL=ON . Currently OpenGL is
|
To enable OpenGL support, configure OpenCV using CMake with WITH_OPENGL=ON . Currently OpenGL is
|
||||||
supported only with WIN32, GTK and Qt backends on Windows and Linux (MacOS and Android are not
|
supported only with WIN32, GTK and Qt backends on Windows and Linux (MacOS and Android are not
|
||||||
supported). For GTK backend gtkglext-1.0 library is required.
|
supported). For GTK-2.0 backend gtkglext-1.0 library is required.
|
||||||
|
|
||||||
To use OpenGL functionality you should first create OpenGL context (window or frame buffer). You can
|
To use OpenGL functionality you should first create OpenGL context (window or frame buffer). You can
|
||||||
do this with namedWindow function or with other OpenGL toolkit (GLUT, for example).
|
do this with namedWindow function or with other OpenGL toolkit (GLUT, for example).
|
||||||
|
@ -218,6 +218,9 @@ if(TARGET ocv.3rdparty.gtk3 OR TARGET ocv.3rdparty.gtk2)
|
|||||||
)
|
)
|
||||||
if(__gtk_dependency STREQUAL "ocv.3rdparty.gtk3")
|
if(__gtk_dependency STREQUAL "ocv.3rdparty.gtk3")
|
||||||
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "GTK3")
|
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "GTK3")
|
||||||
|
if(OPENGL_LIBRARIES)
|
||||||
|
list(APPEND HIGHGUI_LIBRARIES "${OPENGL_LIBRARIES}")
|
||||||
|
endif()
|
||||||
elseif(__gtk_dependency STREQUAL "ocv.3rdparty.gtk2")
|
elseif(__gtk_dependency STREQUAL "ocv.3rdparty.gtk2")
|
||||||
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "GTK2")
|
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "GTK2")
|
||||||
else()
|
else()
|
||||||
|
@ -26,7 +26,8 @@ if(WITH_GTK)
|
|||||||
else()
|
else()
|
||||||
ocv_add_external_target(gthread "${GTHREAD_INCLUDE_DIRS}" "${GTHREAD_LIBRARIES}" "HAVE_GTHREAD")
|
ocv_add_external_target(gthread "${GTHREAD_INCLUDE_DIRS}" "${GTHREAD_LIBRARIES}" "HAVE_GTHREAD")
|
||||||
endif()
|
endif()
|
||||||
if((WITH_OPENGL OR HAVE_OPENGL) AND HAVE_GTK2)
|
if((WITH_OPENGL OR HAVE_OPENGL) AND (HAVE_GTK2 OR HAVE_GTK3))
|
||||||
|
if(HAVE_GTK2)
|
||||||
ocv_check_modules(GTKGLEXT gtkglext-1.0)
|
ocv_check_modules(GTKGLEXT gtkglext-1.0)
|
||||||
if(HAVE_GTKGLEXT)
|
if(HAVE_GTKGLEXT)
|
||||||
# HACK for https://github.com/opencv/opencv/issues/20850
|
# HACK for https://github.com/opencv/opencv/issues/20850
|
||||||
@ -37,14 +38,15 @@ if(WITH_GTK)
|
|||||||
list(APPEND GTKGLEXT_INCLUDE_DIRS_EXISTS "${p}")
|
list(APPEND GTKGLEXT_INCLUDE_DIRS_EXISTS "${p}")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
ocv_add_external_target(gtkglext "${GTKGLEXT_INCLUDE_DIRS_EXISTS}" "${GTKGLEXT_LIBRARIES}" "HAVE_GTKGLEXT")
|
ocv_add_external_target(gtkglext "${GTKGLEXT_INCLUDE_DIRS}" "${GTKGLEXT_LIBRARIES}" "HAVE_GTKGLEXT")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
elseif(HAVE_GTK)
|
elseif(HAVE_GTK)
|
||||||
ocv_add_external_target(gtk "${GTK_INCLUDE_DIRS}" "${GTK_LIBRARIES}" "${GTK_DEFINES};HAVE_GTK")
|
ocv_add_external_target(gtk "${GTK_INCLUDE_DIRS}" "${GTK_LIBRARIES}" "${GTK_DEFINES};HAVE_GTK")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_OPENGL AND HAVE_GTKGLEXT)
|
if(WITH_OPENGL)
|
||||||
find_package(OpenGL QUIET)
|
find_package(OpenGL QUIET)
|
||||||
if(OPENGL_FOUND)
|
if(OPENGL_FOUND)
|
||||||
set(HAVE_OPENGL TRUE)
|
set(HAVE_OPENGL TRUE)
|
||||||
|
@ -46,10 +46,7 @@
|
|||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
#if (GTK_MAJOR_VERSION == 3) && defined(HAVE_OPENGL)
|
#if (GTK_MAJOR_VERSION == 2) && defined(HAVE_OPENGL) && !defined(HAVE_GTKGLEXT)
|
||||||
#undef HAVE_OPENGL // no support with GTK3
|
|
||||||
#endif
|
|
||||||
#if defined(HAVE_OPENGL) && !defined(HAVE_GTKGLEXT)
|
|
||||||
#undef HAVE_OPENGL // gtkglext is required
|
#undef HAVE_OPENGL // gtkglext is required
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -68,10 +65,14 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_OPENGL
|
#ifdef HAVE_OPENGL
|
||||||
|
#ifdef GTK_VERSION3
|
||||||
|
#include <gtk/gtkglarea.h>
|
||||||
|
#else
|
||||||
#include <gtk/gtkgl.h>
|
#include <gtk/gtkgl.h>
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <GL/glu.h>
|
#include <GL/glu.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <opencv2/core/utils/logger.hpp>
|
#include <opencv2/core/utils/logger.hpp>
|
||||||
#include "opencv2/imgproc.hpp"
|
#include "opencv2/imgproc.hpp"
|
||||||
@ -570,7 +571,7 @@ struct CvWindow : CvUIBase
|
|||||||
last_key(0), flags(0), status(0),
|
last_key(0), flags(0), status(0),
|
||||||
on_mouse(NULL), on_mouse_param(NULL)
|
on_mouse(NULL), on_mouse_param(NULL)
|
||||||
#ifdef HAVE_OPENGL
|
#ifdef HAVE_OPENGL
|
||||||
,useGl(false), glDrawCallback(NULL), glDrawData(NULL)
|
,useGl(false), glDrawCallback(NULL), glDrawData(NULL), glArea(NULL)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
CV_LOG_INFO(NULL, "OpenCV/UI: creating GTK window: " << window_name);
|
CV_LOG_INFO(NULL, "OpenCV/UI: creating GTK window: " << window_name);
|
||||||
@ -597,6 +598,7 @@ struct CvWindow : CvUIBase
|
|||||||
|
|
||||||
CvOpenGlDrawCallback glDrawCallback;
|
CvOpenGlDrawCallback glDrawCallback;
|
||||||
void* glDrawData;
|
void* glDrawData;
|
||||||
|
GtkWidget* glArea;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -640,7 +642,7 @@ CV_IMPL int cvInitSystem( int argc, char** argv )
|
|||||||
|
|
||||||
setlocale(LC_NUMERIC,"C");
|
setlocale(LC_NUMERIC,"C");
|
||||||
|
|
||||||
#ifdef HAVE_OPENGL
|
#if defined(HAVE_OPENGL) && not defined(GTK_VERSION3) // GTK3+ uses GtkGLArea so no need to check for GtkGLExt
|
||||||
if (!gtk_gl_init_check(&argc, &argv))
|
if (!gtk_gl_init_check(&argc, &argv))
|
||||||
{
|
{
|
||||||
hasError = true;
|
hasError = true;
|
||||||
@ -907,11 +909,42 @@ double cvGetOpenGlProp_GTK(const char* name)
|
|||||||
// OpenGL support
|
// OpenGL support
|
||||||
|
|
||||||
#ifdef HAVE_OPENGL
|
#ifdef HAVE_OPENGL
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#ifdef GTK_VERSION3
|
||||||
|
|
||||||
|
void glRealizeCallback(GtkGLArea* area, gpointer user_data) {
|
||||||
|
CV_UNUSED(user_data);
|
||||||
|
gtk_gl_area_make_current(area);
|
||||||
|
if (gtk_gl_area_get_error(area) != NULL)
|
||||||
|
CV_Error(cv::Error::OpenGlApiCallError, "OpenGL context is not initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean glRenderCallback(GtkGLArea* area, GdkGLContext* context, gpointer user_data) {
|
||||||
|
CV_UNUSED(context);
|
||||||
|
CvWindow* window = (CvWindow*)user_data;
|
||||||
|
gtk_gl_area_make_current(area);
|
||||||
|
if (gtk_gl_area_get_error(area) != NULL) {
|
||||||
|
CV_Error(cv::Error::OpenGlApiCallError, "OpenGL context is not initialized");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if(window->glDrawCallback) {
|
||||||
|
window->glDrawCallback(window->glDrawData);
|
||||||
|
}
|
||||||
|
// gtk_gl_area_queue_render(area);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void createGlContext(CvWindow* window)
|
void createGlContext(CvWindow* window)
|
||||||
{
|
{
|
||||||
|
#ifdef GTK_VERSION3
|
||||||
|
g_signal_connect(window->glArea, "realize", G_CALLBACK(glRealizeCallback), window);
|
||||||
|
g_signal_connect(window->glArea, "render", G_CALLBACK(glRenderCallback), window);
|
||||||
|
#else
|
||||||
|
|
||||||
GdkGLConfig* glconfig;
|
GdkGLConfig* glconfig;
|
||||||
|
|
||||||
// Try double-buffered visual
|
// Try double-buffered visual
|
||||||
@ -923,11 +956,24 @@ namespace
|
|||||||
if (!gtk_widget_set_gl_capability(window->widget, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
|
if (!gtk_widget_set_gl_capability(window->widget, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
|
||||||
CV_Error( cv::Error::OpenGlApiCallError, "Can't Create A GL Device Context" );
|
CV_Error( cv::Error::OpenGlApiCallError, "Can't Create A GL Device Context" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
window->useGl = true;
|
window->useGl = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawGl(CvWindow* window)
|
void drawGl(CvWindow* window)
|
||||||
{
|
{
|
||||||
|
#ifdef GTK_VERSION3
|
||||||
|
|
||||||
|
GtkGLArea* gtkGlArea = GTK_GL_AREA(window->glArea);
|
||||||
|
if (gtk_gl_area_get_error(gtkGlArea) != NULL)
|
||||||
|
CV_Error(cv::Error::OpenGlApiCallError, "Can't Activate The GL Rendering Context");
|
||||||
|
|
||||||
|
if (window->glDrawCallback)
|
||||||
|
window->glDrawCallback(window->glDrawData);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
GdkGLContext* glcontext = gtk_widget_get_gl_context(window->widget);
|
GdkGLContext* glcontext = gtk_widget_get_gl_context(window->widget);
|
||||||
GdkGLDrawable* gldrawable = gtk_widget_get_gl_drawable(window->widget);
|
GdkGLDrawable* gldrawable = gtk_widget_get_gl_drawable(window->widget);
|
||||||
|
|
||||||
@ -947,6 +993,8 @@ namespace
|
|||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
gdk_gl_drawable_gl_end(gldrawable);
|
gdk_gl_drawable_gl_end(gldrawable);
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1041,12 +1089,27 @@ static std::shared_ptr<CvWindow> namedWindow_(const std::string& name, int flags
|
|||||||
|
|
||||||
window->frame = gtk_window_new( GTK_WINDOW_TOPLEVEL );
|
window->frame = gtk_window_new( GTK_WINDOW_TOPLEVEL );
|
||||||
|
|
||||||
window->paned = gtk_vbox_new( FALSE, 0 );
|
|
||||||
window->widget = cvImageWidgetNew( flags );
|
window->widget = cvImageWidgetNew( flags );
|
||||||
|
|
||||||
|
#if defined(HAVE_OPENGL) && defined(GTK_VERSION3)
|
||||||
|
if (flags & cv::WINDOW_OPENGL) {
|
||||||
|
window->glArea = gtk_gl_area_new();
|
||||||
|
gtk_container_add(GTK_CONTAINER(window->frame), window->glArea);
|
||||||
|
gtk_widget_show(window->glArea);
|
||||||
|
} else {
|
||||||
|
window->paned = gtk_vbox_new( FALSE, 0 );
|
||||||
gtk_box_pack_end( GTK_BOX(window->paned), window->widget, TRUE, TRUE, 0 );
|
gtk_box_pack_end( GTK_BOX(window->paned), window->widget, TRUE, TRUE, 0 );
|
||||||
gtk_widget_show( window->widget );
|
gtk_widget_show( window->widget );
|
||||||
gtk_container_add( GTK_CONTAINER(window->frame), window->paned );
|
gtk_container_add( GTK_CONTAINER(window->frame), window->paned );
|
||||||
gtk_widget_show( window->paned );
|
gtk_widget_show( window->paned );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
window->paned = gtk_vbox_new( FALSE, 0 );
|
||||||
|
gtk_box_pack_end( GTK_BOX(window->paned), window->widget, TRUE, TRUE, 0 );
|
||||||
|
gtk_widget_show( window->widget );
|
||||||
|
gtk_container_add( GTK_CONTAINER(window->frame), window->paned );
|
||||||
|
gtk_widget_show( window->paned );
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_OPENGL
|
#ifndef HAVE_OPENGL
|
||||||
if (flags & cv::WINDOW_OPENGL)
|
if (flags & cv::WINDOW_OPENGL)
|
||||||
@ -1122,9 +1185,6 @@ static std::shared_ptr<CvWindow> namedWindow_(const std::string& name, int flags
|
|||||||
|
|
||||||
CV_IMPL void cvSetOpenGlContext(const char* name)
|
CV_IMPL void cvSetOpenGlContext(const char* name)
|
||||||
{
|
{
|
||||||
GdkGLContext* glcontext;
|
|
||||||
GdkGLDrawable* gldrawable;
|
|
||||||
|
|
||||||
CV_Assert(name && "NULL name string");
|
CV_Assert(name && "NULL name string");
|
||||||
|
|
||||||
CV_LOCK_MUTEX();
|
CV_LOCK_MUTEX();
|
||||||
@ -1136,11 +1196,24 @@ CV_IMPL void cvSetOpenGlContext(const char* name)
|
|||||||
if (!window->useGl)
|
if (!window->useGl)
|
||||||
CV_Error( cv::Error::OpenGlNotSupported, "Window doesn't support OpenGL" );
|
CV_Error( cv::Error::OpenGlNotSupported, "Window doesn't support OpenGL" );
|
||||||
|
|
||||||
|
#ifdef GTK_VERSION3
|
||||||
|
|
||||||
|
if(gtk_gl_area_get_error(GTK_GL_AREA(window->glArea)) != NULL)
|
||||||
|
CV_Error( cv::Error::OpenGlApiCallError, "Can't Activate The GL Rendering Context");
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
GdkGLContext* glcontext;
|
||||||
|
GdkGLDrawable* gldrawable;
|
||||||
|
|
||||||
glcontext = gtk_widget_get_gl_context(window->widget);
|
glcontext = gtk_widget_get_gl_context(window->widget);
|
||||||
gldrawable = gtk_widget_get_gl_drawable(window->widget);
|
gldrawable = gtk_widget_get_gl_drawable(window->widget);
|
||||||
|
|
||||||
if (!gdk_gl_drawable_make_current(gldrawable, glcontext))
|
if (!gdk_gl_drawable_make_current(gldrawable, glcontext))
|
||||||
CV_Error( cv::Error::OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
|
CV_Error( cv::Error::OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CV_IMPL void cvUpdateWindow(const char* name)
|
CV_IMPL void cvUpdateWindow(const char* name)
|
||||||
@ -1154,9 +1227,22 @@ CV_IMPL void cvUpdateWindow(const char* name)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// window does not refresh without this
|
// window does not refresh without this
|
||||||
|
#ifdef GTK_VERSION3
|
||||||
|
|
||||||
|
if ( GTK_IS_GL_AREA(window->glArea) ){
|
||||||
|
gtk_gl_area_queue_render(GTK_GL_AREA(window->glArea));
|
||||||
|
} else {
|
||||||
gtk_widget_queue_draw( GTK_WIDGET(window->widget));
|
gtk_widget_queue_draw( GTK_WIDGET(window->widget));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
gtk_widget_queue_draw( GTK_WIDGET(window->widget) );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
CV_IMPL void cvSetOpenGlDrawCallback(const char* name, CvOpenGlDrawCallback callback, void* userdata)
|
CV_IMPL void cvSetOpenGlDrawCallback(const char* name, CvOpenGlDrawCallback callback, void* userdata)
|
||||||
{
|
{
|
||||||
CV_Assert(name && "NULL name string");
|
CV_Assert(name && "NULL name string");
|
||||||
|
@ -6,6 +6,9 @@ if(UNIX)
|
|||||||
find_package(X11 QUIET)
|
find_package(X11 QUIET)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(PkgConfig QUIET)
|
||||||
|
pkg_search_module(EPOXY QUIET epoxy)
|
||||||
|
|
||||||
SET(OPENCV_OPENGL_SAMPLES_REQUIRED_DEPS
|
SET(OPENCV_OPENGL_SAMPLES_REQUIRED_DEPS
|
||||||
opencv_core
|
opencv_core
|
||||||
opencv_imgproc
|
opencv_imgproc
|
||||||
@ -21,6 +24,9 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
|
|||||||
if(NOT X11_FOUND)
|
if(NOT X11_FOUND)
|
||||||
ocv_list_filterout(all_samples "opengl_interop")
|
ocv_list_filterout(all_samples "opengl_interop")
|
||||||
endif()
|
endif()
|
||||||
|
if(NOT EPOXY_FOUND)
|
||||||
|
ocv_list_filterout(all_samples "opengl3_2")
|
||||||
|
endif()
|
||||||
foreach(sample_filename ${all_samples})
|
foreach(sample_filename ${all_samples})
|
||||||
ocv_define_sample(tgt ${sample_filename} opengl)
|
ocv_define_sample(tgt ${sample_filename} opengl)
|
||||||
ocv_target_link_libraries(${tgt} PRIVATE "${OPENGL_LIBRARIES}" "${OPENCV_OPENGL_SAMPLES_REQUIRED_DEPS}")
|
ocv_target_link_libraries(${tgt} PRIVATE "${OPENGL_LIBRARIES}" "${OPENCV_OPENGL_SAMPLES_REQUIRED_DEPS}")
|
||||||
@ -28,6 +34,10 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
|
|||||||
ocv_target_link_libraries(${tgt} PRIVATE ${X11_LIBRARIES})
|
ocv_target_link_libraries(${tgt} PRIVATE ${X11_LIBRARIES})
|
||||||
ocv_target_include_directories(${tgt} ${X11_INCLUDE_DIR})
|
ocv_target_include_directories(${tgt} ${X11_INCLUDE_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
if(sample_filename STREQUAL "opengl3_2.cpp")
|
||||||
|
ocv_target_link_libraries(${tgt} PRIVATE ${EPOXY_LIBRARIES})
|
||||||
|
ocv_target_include_directories(${tgt} PRIVATE ${EPOXY_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
169
samples/opengl/opengl3_2.cpp
Normal file
169
samples/opengl/opengl3_2.cpp
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <epoxy/gl.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
|
#define NOMINMAX 1
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenGL/gl.h>
|
||||||
|
#include <OpenGL/glu.h>
|
||||||
|
#else
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <GL/glu.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "opencv2/core.hpp"
|
||||||
|
#include "opencv2/core/opengl.hpp"
|
||||||
|
#include "opencv2/core/cuda.hpp"
|
||||||
|
#include "opencv2/highgui.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
using namespace cv::cuda;
|
||||||
|
|
||||||
|
const int win_width = 800;
|
||||||
|
const int win_height = 640;
|
||||||
|
|
||||||
|
struct DrawData
|
||||||
|
{
|
||||||
|
GLuint vao, vbo, program, textureID;
|
||||||
|
};
|
||||||
|
|
||||||
|
static cv::Mat rot(float angle)
|
||||||
|
{
|
||||||
|
cv::Mat R_y = (cv::Mat_<float>(4,4) <<
|
||||||
|
cos(angle), 0, sin(angle), 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
-sin(angle), 0, cos(angle), 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
|
||||||
|
return R_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLuint create_shader(const char* source, GLenum type) {
|
||||||
|
GLuint shader = glCreateShader(type);
|
||||||
|
glShaderSource(shader, 1, &source, NULL);
|
||||||
|
glCompileShader(shader);
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw(void* userdata) {
|
||||||
|
DrawData* data = static_cast<DrawData*>(userdata);
|
||||||
|
static float angle = 0.0f;
|
||||||
|
angle += 1.f;
|
||||||
|
|
||||||
|
cv::Mat trans = rot(CV_PI * angle / 360.f);
|
||||||
|
|
||||||
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glUseProgram(data->program);
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(data->program, "transform"), 1, GL_FALSE, trans.ptr<float>());
|
||||||
|
glBindTexture(GL_TEXTURE_2D, data->textureID);
|
||||||
|
glBindVertexArray(data->vao);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
string filename;
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
cout << "Usage: " << argv[0] << " image" << endl;
|
||||||
|
filename = "baboon.jpg";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
filename = argv[1];
|
||||||
|
|
||||||
|
Mat img = imread(samples::findFile(filename));
|
||||||
|
if (img.empty())
|
||||||
|
{
|
||||||
|
cerr << "Can't open image " << filename << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
flip(img, img, 0);
|
||||||
|
|
||||||
|
namedWindow("OpenGL", WINDOW_OPENGL);
|
||||||
|
resizeWindow("OpenGL", win_width, win_height);
|
||||||
|
|
||||||
|
DrawData data;
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
const char *vertex_shader_source =
|
||||||
|
"#version 330 core\n"
|
||||||
|
"layout (location = 0) in vec3 position;\n"
|
||||||
|
"layout (location = 1) in vec2 texCoord;\n"
|
||||||
|
"out vec2 TexCoord;\n"
|
||||||
|
"uniform mat4 transform;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" gl_Position = transform * vec4(position, 1.0);\n"
|
||||||
|
" TexCoord = texCoord;\n"
|
||||||
|
"}\n";
|
||||||
|
const char *fragment_shader_source =
|
||||||
|
"#version 330 core\n"
|
||||||
|
"in vec2 TexCoord;\n"
|
||||||
|
"out vec4 color;\n"
|
||||||
|
"uniform sampler2D ourTexture;\n"
|
||||||
|
"void main() {\n"
|
||||||
|
" color = texture(ourTexture, TexCoord);\n"
|
||||||
|
"}\n";
|
||||||
|
data.program = glCreateProgram();
|
||||||
|
GLuint vertex_shader = create_shader(vertex_shader_source, GL_VERTEX_SHADER);
|
||||||
|
GLuint fragment_shader = create_shader(fragment_shader_source, GL_FRAGMENT_SHADER);
|
||||||
|
glAttachShader(data.program, vertex_shader);
|
||||||
|
glAttachShader(data.program, fragment_shader);
|
||||||
|
glLinkProgram(data.program);
|
||||||
|
glUseProgram(data.program);
|
||||||
|
|
||||||
|
GLfloat vertices[] = {
|
||||||
|
// Positions // Texture Coords
|
||||||
|
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top Right
|
||||||
|
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right
|
||||||
|
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Left
|
||||||
|
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f // Bottom Left
|
||||||
|
};
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &data.vao);
|
||||||
|
glGenBuffers(1, &data.vbo);
|
||||||
|
glBindVertexArray(data.vao);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, data.vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// Position attribute
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
// Texture Coord attribute
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glBindVertexArray(0); // Unbind VAO
|
||||||
|
|
||||||
|
|
||||||
|
// Image to texture
|
||||||
|
glGenTextures(1, &data.textureID);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, data.textureID);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.cols, img.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, img.data);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
setOpenGlDrawCallback("OpenGL", draw, &data);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
updateWindow("OpenGL");
|
||||||
|
char key = (char)waitKey(40);
|
||||||
|
if (key == 27)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setOpenGlDrawCallback("OpenGL", 0, 0);
|
||||||
|
destroyAllWindows();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user