Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork56.4k
Support OpenGL GTK3 New API#25822
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes from1 commit
b42405ac035d9328fb35c74c1fcbb977644b9b912e174265741efb5bc76cdb48ca3ec1File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
- Loading branch information
Uh oh!
There was an error while loading.Please reload this page.
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1464,9 +1464,14 @@ if(WITH_GTK OR HAVE_GTK) | ||
| else() | ||
| status(" GTK+:" "NO") | ||
| endif() | ||
| if(HAVE_GTK) | ||
| status( " GThread :" HAVE_GTHREAD THEN "YES (ver ${GTHREAD_VERSION})" ELSE NO) | ||
| if(HAVE_GTK3) | ||
| status( " Epoxy:" HAVE_EPOXY THEN "YES (ver ${EPOXY_VERSION})" ELSE NO) | ||
mqcmd196 marked this conversation as resolved. OutdatedShow resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| else() | ||
| status( " GtkGlExt:" HAVE_GTKGLEXT THEN "YES (ver ${GTKGLEXT_VERSION})" ELSE NO) | ||
| endif() | ||
| endif() | ||
| endif() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -62,7 +62,7 @@ endif() | ||
| # --- OpenGl --- | ||
| ocv_clear_vars(HAVE_OPENGL HAVE_QT_OPENGL) | ||
| if(WITH_OPENGL) | ||
| if(WITH_WIN32UI OR (HAVE_QT AND QT_QTOPENGL_FOUND) OR(HAVE_GTK3 AND HAVE_EPOXY) OR (HAVE_GTK AND NOT HAVE_GTK3 ANDHAVE_GTKGLEXT)) | ||
mqcmd196 marked this conversation as resolved. OutdatedShow resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| find_package (OpenGL QUIET) | ||
| if(OPENGL_FOUND) | ||
| set(HAVE_OPENGL TRUE) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -46,10 +46,7 @@ | ||
| #include <gtk/gtk.h> | ||
| #if (GTK_MAJOR_VERSION == 2) && defined(HAVE_OPENGL) && !defined(HAVE_GTKGLEXT) | ||
| #undef HAVE_OPENGL // gtkglext is required | ||
| #endif | ||
| @@ -68,9 +65,14 @@ | ||
| #endif | ||
| #ifdef HAVE_OPENGL | ||
| #ifdef GTK_VERSION3 | ||
| #include <gtk/gtkglarea.h> | ||
| #include <epoxy/gl.h> | ||
mqcmd196 marked this conversation as resolved. OutdatedShow resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| #else | ||
| #include <gtk/gtkgl.h> | ||
| #include <GL/glu.h> | ||
| #endif | ||
| #include <GL/gl.h> | ||
| #endif | ||
| #include <opencv2/core/utils/logger.hpp> | ||
| @@ -570,7 +572,7 @@ struct CvWindow : CvUIBase | ||
| last_key(0), flags(0), status(0), | ||
| on_mouse(NULL), on_mouse_param(NULL) | ||
| #ifdef HAVE_OPENGL | ||
| ,useGl(false), glDrawCallback(NULL), glDrawData(NULL), glArea(NULL) | ||
| #endif | ||
| { | ||
| CV_LOG_INFO(NULL, "OpenCV/UI: creating GTK window: " << window_name); | ||
| @@ -597,6 +599,7 @@ struct CvWindow : CvUIBase | ||
| CvOpenGlDrawCallback glDrawCallback; | ||
| void* glDrawData; | ||
| GtkWidget* glArea; | ||
| #endif | ||
| }; | ||
| @@ -640,7 +643,7 @@ CV_IMPL int cvInitSystem( int argc, char** argv ) | ||
| setlocale(LC_NUMERIC,"C"); | ||
| #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)) | ||
| { | ||
| hasError = true; | ||
| @@ -907,11 +910,40 @@ double cvGetOpenGlProp_GTK(const char* name) | ||
| // OpenGL support | ||
| #ifdef HAVE_OPENGL | ||
| namespace | ||
| { | ||
| #ifdef GTK_VERSION3 | ||
| void glRealizeCallback(GtkGLArea* area, gpointer 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){ | ||
| 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) | ||
| { | ||
| #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; | ||
| // Try double-buffered visual | ||
| @@ -923,11 +955,24 @@ namespace | ||
| 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" ); | ||
| #endif | ||
| window->useGl = true; | ||
| } | ||
| 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); | ||
| GdkGLDrawable* gldrawable = gtk_widget_get_gl_drawable(window->widget); | ||
| @@ -947,6 +992,8 @@ namespace | ||
| glFlush(); | ||
| gdk_gl_drawable_gl_end(gldrawable); | ||
| #endif | ||
| } | ||
| } | ||
| @@ -1041,12 +1088,27 @@ static std::shared_ptr<CvWindow> namedWindow_(const std::string& name, int flags | ||
| window->frame = gtk_window_new( GTK_WINDOW_TOPLEVEL ); | ||
| 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_widget_show( window->widget ); | ||
| gtk_container_add( GTK_CONTAINER(window->frame), 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 | ||
| if (flags & cv::WINDOW_OPENGL) | ||
| @@ -1122,9 +1184,6 @@ static std::shared_ptr<CvWindow> namedWindow_(const std::string& name, int flags | ||
| CV_IMPL void cvSetOpenGlContext(const char* name) | ||
| { | ||
| CV_Assert(name && "NULL name string"); | ||
| CV_LOCK_MUTEX(); | ||
| @@ -1136,11 +1195,24 @@ CV_IMPL void cvSetOpenGlContext(const char* name) | ||
| if (!window->useGl) | ||
| 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); | ||
| gldrawable = gtk_widget_get_gl_drawable(window->widget); | ||
| if (!gdk_gl_drawable_make_current(gldrawable, glcontext)) | ||
| CV_Error( cv::Error::OpenGlApiCallError, "Can't Activate The GL Rendering Context" ); | ||
| #endif | ||
| } | ||
| CV_IMPL void cvUpdateWindow(const char* name) | ||
| @@ -1154,7 +1226,20 @@ CV_IMPL void cvUpdateWindow(const char* name) | ||
| return; | ||
| // 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)); | ||
| } | ||
| #else | ||
| gtk_widget_queue_draw( GTK_WIDGET(window->widget) ); | ||
| #endif | ||
| } | ||
| CV_IMPL void cvSetOpenGlDrawCallback(const char* name, CvOpenGlDrawCallback callback, void* userdata) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -253,6 +253,77 @@ TEST(Highgui_GUI, currentUIFramework) | ||
| EXPECT_GT(framework.size(), 0); // builtin backends | ||
| #endif | ||
| } | ||
| #if (!defined(ENABLE_PLUGINS) \ | ||
| && !defined HAVE_GTK \ | ||
| && !defined HAVE_QT \ | ||
| && !defined HAVE_WIN32UI \ | ||
| && !defined HAVE_COCOA \ | ||
| && !defined HAVE_WAYLAND \ | ||
| ) || !defined(HAVE_OPENGL) | ||
| TEST(Highgui_GUI, DISABLED_gl) | ||
| #else | ||
| #include<epoxy/gl.h> | ||
| #include<GL/gl.h> | ||
| static GLuint create_shader(const char* source, GLenum type) { | ||
| GLuint shader = glCreateShader(type); | ||
| glShaderSource(shader, 1, &source, NULL); | ||
| glCompileShader(shader); | ||
| return shader; | ||
| } | ||
| struct DrawData | ||
| { | ||
| GLuint vao, vbo, program; | ||
| }; | ||
| void draw(void* userdata){ | ||
| DrawData* data = static_cast<DrawData*>(userdata); | ||
| glBindVertexArray(data->vao); | ||
| glDrawArrays(GL_TRIANGLES, 0, 3); | ||
| glBindVertexArray(0); | ||
| } | ||
| TEST(Highgui_GUI, gl) | ||
| #endif | ||
| { | ||
| const std::string window_name("gl_test_window"); | ||
| const Size image_size(800, 600); | ||
| EXPECT_NO_THROW(destroyAllWindows()); | ||
| ASSERT_NO_THROW(namedWindow(window_name, WINDOW_OPENGL)); | ||
| ASSERT_NO_THROW(resizeWindow(window_name, image_size)); | ||
| DrawData data; | ||
| const char *vertex_shader_source = | ||
| "#version 330 core\n" | ||
| "layout (location = 0) in vec3 position;\n" | ||
| "void main() {\n" | ||
| " gl_Position = vec4(position, 1.0);\n" | ||
| "}\n"; | ||
| const char *fragment_shader_source = | ||
| "#version 330 core\n" | ||
| "out vec4 color;\n" | ||
| "void main() {\n" | ||
| " color = vec4(1.0, 1.0, 1.0, 1.0); // white\n" | ||
| "}\n"; | ||
| GLuint vertex_shader = create_shader(vertex_shader_source, GL_VERTEX_SHADER); | ||
| GLuint fragment_shader = create_shader(fragment_shader_source, GL_FRAGMENT_SHADER); | ||
| data.program = glCreateProgram(); | ||
| glAttachShader(data.program, vertex_shader); | ||
| glAttachShader(data.program, fragment_shader); | ||
| glLinkProgram(data.program); | ||
| glUseProgram(data.program); | ||
| GLfloat vertices[] = { | ||
| 0.0f, 0.5f, 0.0f, | ||
| -0.5f, -0.5f, 0.0f, | ||
| 0.5f, -0.5f, 0.0f | ||
| }; | ||
| glGenVertexArrays(1, &data.vao); | ||
| glBindVertexArray(data.vao); | ||
| glGenBuffers(1, &data.vbo); | ||
| glBindBuffer(GL_ARRAY_BUFFER, data.vbo); | ||
| glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); | ||
| glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); | ||
| glEnableVertexAttribArray(0); | ||
| glBindVertexArray(0); | ||
| ASSERT_NO_THROW(setOpenGlDrawCallback(window_name, draw, &data)); | ||
| EXPECT_NO_THROW(waitKey(10000)); | ||
| EXPECT_NO_THROW(setOpenGlDrawCallback(window_name, 0)); | ||
| EXPECT_NO_THROW(destroyAllWindows()); | ||
mqcmd196 marked this conversation as resolved. OutdatedShow resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| } | ||
| }} // namespace | ||