diff --git a/Makefile.in b/Makefile.in
index 4b0c2dd420..54fbec3abd 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -2292,9 +2292,11 @@ COND_TOOLKIT_MSW_WEBVIEW_HDR_PLATFORM = \
@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2@OPENGL_HDR_PLATFORM \
@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2@ = wx/gtk/glcanvas.h wx/unix/glx11.h
@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3@OPENGL_HDR_PLATFORM \
-@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3@ = wx/gtk/glcanvas.h wx/unix/glx11.h
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3@ = wx/gtk/glcanvas.h wx/unix/glegl.h \
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_3@ wx/unix/glx11.h
@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4@OPENGL_HDR_PLATFORM \
-@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4@ = wx/gtk/glcanvas.h wx/unix/glx11.h
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4@ = wx/gtk/glcanvas.h wx/unix/glegl.h \
+@COND_TOOLKIT_GTK_TOOLKIT_VERSION_4@ wx/unix/glx11.h
@COND_TOOLKIT_MOTIF@OPENGL_HDR_PLATFORM = wx/x11/glcanvas.h wx/unix/glx11.h
@COND_TOOLKIT_MSW@OPENGL_HDR_PLATFORM = wx/msw/glcanvas.h
@COND_TOOLKIT_OSX_COCOA@OPENGL_HDR_PLATFORM = wx/osx/glcanvas.h
@@ -13088,10 +13090,12 @@ COND_USE_SOVERSOLARIS_1___gldll___so_symlinks_uninst_cmd = rm -f \
@COND_USE_SOVERSOLARIS_1@__gldll___so_symlinks_uninst_cmd = $(COND_USE_SOVERSOLARIS_1___gldll___so_symlinks_uninst_cmd)
@COND_PLATFORM_WIN32_1@__gldll___win32rc = gldll_version_rc.o
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@__OPENGL_SRC_PLATFORM_OBJECTS \
-@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@ = gldll_glx11.o \
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@ = gldll_glegl.o \
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@ gldll_glx11.o \
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@ gldll_gtk_glcanvas.o
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@__OPENGL_SRC_PLATFORM_OBJECTS \
-@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ = gldll_glx11.o \
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ = gldll_glegl.o \
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ gldll_glx11.o \
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ gldll_gtk_glcanvas.o
@COND_TOOLKIT_COCOA@__OPENGL_SRC_PLATFORM_OBJECTS = \
@COND_TOOLKIT_COCOA@ gldll_src_cocoa_glcanvas.o
@@ -13131,10 +13135,12 @@ COND_SHARED_0_USE_GUI_1_USE_OPENGL_1___gllib___depname = \
@COND_USE_PCH_1@_____pch_wxprec_gllib_wx_wxprec_h_gch___depname \
@COND_USE_PCH_1@ = ./.pch/wxprec_gllib/wx/wxprec.h.gch
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@__OPENGL_SRC_PLATFORM_OBJECTS_1 \
-@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@ = gllib_glx11.o \
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@ = gllib_glegl.o \
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@ gllib_glx11.o \
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@ gllib_gtk_glcanvas.o
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@__OPENGL_SRC_PLATFORM_OBJECTS_1 \
-@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ = gllib_glx11.o \
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ = gllib_glegl.o \
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ gllib_glx11.o \
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ gllib_gtk_glcanvas.o
@COND_TOOLKIT_COCOA@__OPENGL_SRC_PLATFORM_OBJECTS_1 = \
@COND_TOOLKIT_COCOA@ gllib_src_cocoa_glcanvas.o
@@ -36732,6 +36738,12 @@ gldll_msw_glcanvas.o: $(srcdir)/src/msw/glcanvas.cpp $(GLDLL_ODEP)
@COND_TOOLKIT_OSX_IPHONE@gldll_glcanvas_osx.o: $(srcdir)/src/osx/glcanvas_osx.cpp $(GLDLL_ODEP)
@COND_TOOLKIT_OSX_IPHONE@ $(CXXC) -c -o $@ $(GLDLL_CXXFLAGS) $(srcdir)/src/osx/glcanvas_osx.cpp
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@gldll_glegl.o: $(srcdir)/src/unix/glegl.cpp $(GLDLL_ODEP)
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ $(CXXC) -c -o $@ $(GLDLL_CXXFLAGS) $(srcdir)/src/unix/glegl.cpp
+
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@gldll_glegl.o: $(srcdir)/src/unix/glegl.cpp $(GLDLL_ODEP)
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@ $(CXXC) -c -o $@ $(GLDLL_CXXFLAGS) $(srcdir)/src/unix/glegl.cpp
+
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@gldll_glx11.o: $(srcdir)/src/unix/glx11.cpp $(GLDLL_ODEP)
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ $(CXXC) -c -o $@ $(GLDLL_CXXFLAGS) $(srcdir)/src/unix/glx11.cpp
@@ -36792,6 +36804,12 @@ gllib_msw_glcanvas.o: $(srcdir)/src/msw/glcanvas.cpp $(GLLIB_ODEP)
@COND_TOOLKIT_OSX_IPHONE@gllib_glcanvas_osx.o: $(srcdir)/src/osx/glcanvas_osx.cpp $(GLLIB_ODEP)
@COND_TOOLKIT_OSX_IPHONE@ $(CXXC) -c -o $@ $(GLLIB_CXXFLAGS) $(srcdir)/src/osx/glcanvas_osx.cpp
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@gllib_glegl.o: $(srcdir)/src/unix/glegl.cpp $(GLLIB_ODEP)
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ $(CXXC) -c -o $@ $(GLLIB_CXXFLAGS) $(srcdir)/src/unix/glegl.cpp
+
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@gllib_glegl.o: $(srcdir)/src/unix/glegl.cpp $(GLLIB_ODEP)
+@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_3@ $(CXXC) -c -o $@ $(GLLIB_CXXFLAGS) $(srcdir)/src/unix/glegl.cpp
+
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@gllib_glx11.o: $(srcdir)/src/unix/glx11.cpp $(GLLIB_ODEP)
@COND_PLATFORM_WIN32_0_TOOLKIT_GTK_TOOLKIT_VERSION_4@ $(CXXC) -c -o $@ $(GLLIB_CXXFLAGS) $(srcdir)/src/unix/glx11.cpp
diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl
index b5c240db5f..983df6483b 100644
--- a/build/bakefiles/files.bkl
+++ b/build/bakefiles/files.bkl
@@ -3191,10 +3191,12 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
src/osx/iphone/glcanvas.mm src/osx/glcanvas_osx.cpp
src/cocoa/glcanvas.mm
+ src/unix/glegl.cpp
src/unix/glx11.cpp
src/gtk/glcanvas.cpp
+ src/unix/glegl.cpp
src/unix/glx11.cpp
src/gtk/glcanvas.cpp
@@ -3222,10 +3224,12 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
wx/cocoa/glcanvas.h
wx/gtk/glcanvas.h
+ wx/unix/glegl.h
wx/unix/glx11.h
wx/gtk/glcanvas.h
+ wx/unix/glegl.h
wx/unix/glx11.h
diff --git a/build/cmake/files.cmake b/build/cmake/files.cmake
index f3db68b0bd..e60edd09fa 100644
--- a/build/cmake/files.cmake
+++ b/build/cmake/files.cmake
@@ -3036,11 +3036,13 @@ set(OPENGL_MSW_HDR
set(OPENGL_GTK_SRC
src/gtk/glcanvas.cpp
src/unix/glx11.cpp
+ src/unix/glegl.cpp
)
set(OPENGL_GTK_HDR
wx/gtk/glcanvas.h
wx/unix/glx11.h
+ wx/unix/glegl.h
)
set(OPENGL_OSX_COCOA_SRC
diff --git a/build/cmake/init.cmake b/build/cmake/init.cmake
index d013e92a5a..5487ad92cf 100644
--- a/build/cmake/init.cmake
+++ b/build/cmake/init.cmake
@@ -385,6 +385,9 @@ if(wxUSE_GUI)
set(OPENGL_LIBRARIES "-framework OpenGLES" "-framework QuartzCore")
else()
find_package(OpenGL)
+ if(WXGTK3 AND OpenGL_EGL_FOUND)
+ set(wxUSE_GLCANVAS_EGL ON)
+ endif()
endif()
if(NOT OPENGL_FOUND)
message(WARNING "opengl not found, wxGLCanvas won't be available")
diff --git a/build/cmake/setup.h.in b/build/cmake/setup.h.in
index 77f5c8111e..b71e097360 100644
--- a/build/cmake/setup.h.in
+++ b/build/cmake/setup.h.in
@@ -549,6 +549,8 @@
#cmakedefine01 wxUSE_GLCANVAS
+#cmakedefine01 wxUSE_GLCANVAS_EGL
+
#cmakedefine01 wxUSE_RICHTEXT
diff --git a/build/files b/build/files
index 759ab54db1..490e4dfb7f 100644
--- a/build/files
+++ b/build/files
@@ -2973,10 +2973,12 @@ OPENGL_MSW_SRC =
OPENGL_GTK_HDR =
wx/gtk/glcanvas.h
+ wx/unix/glegl.h
wx/unix/glx11.h
OPENGL_GTK_SRC =
src/gtk/glcanvas.cpp
+ src/unix/glegl.cpp
src/unix/glx11.cpp
OPENGL_MSW_HDR =
diff --git a/configure b/configure
index 968e728974..93c0f23a50 100755
--- a/configure
+++ b/configure
@@ -953,6 +953,8 @@ CXXFLAGS_VISIBILITY
CFLAGS_VISIBILITY
MesaGL_LIBS
MesaGL_CFLAGS
+EGL_LIBS
+EGL_CFLAGS
GLU_LIBS
GLU_CFLAGS
GL_LIBS
@@ -1029,7 +1031,6 @@ infodir
docdir
oldincludedir
includedir
-runstatedir
localstatedir
sharedstatedir
sysconfdir
@@ -1398,6 +1399,8 @@ GL_CFLAGS
GL_LIBS
GLU_CFLAGS
GLU_LIBS
+EGL_CFLAGS
+EGL_LIBS
MesaGL_CFLAGS
MesaGL_LIBS
LIBSECRET_CFLAGS
@@ -1458,7 +1461,6 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
-runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1711,15 +1713,6 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
- -runstatedir | --runstatedir | --runstatedi | --runstated \
- | --runstate | --runstat | --runsta | --runst | --runs \
- | --run | --ru | --r)
- ac_prev=runstatedir ;;
- -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
- | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
- | --run=* | --ru=* | --r=*)
- runstatedir=$ac_optarg ;;
-
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1857,7 +1850,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir runstatedir
+ libdir localedir mandir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@@ -2010,7 +2003,6 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
- --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@@ -2413,6 +2405,8 @@ Some influential environment variables:
GL_LIBS linker flags for GL, overriding pkg-config
GLU_CFLAGS C compiler flags for GLU, overriding pkg-config
GLU_LIBS linker flags for GLU, overriding pkg-config
+ EGL_CFLAGS C compiler flags for EGL, overriding pkg-config
+ EGL_LIBS linker flags for EGL, overriding pkg-config
MesaGL_CFLAGS
C compiler flags for MesaGL, overriding pkg-config
MesaGL_LIBS linker flags for MesaGL, overriding pkg-config
@@ -28269,6 +28263,90 @@ fi
found_gl=1
OPENGL_LIBS="-lGL -lGLU"
+
+ if test "$WXGTK3" = 1; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for EGL" >&5
+$as_echo_n "checking for EGL... " >&6; }
+
+if test -n "$PKG_CONFIG"; then
+ if test -n "$EGL_CFLAGS"; then
+ pkg_cv_EGL_CFLAGS="$EGL_CFLAGS"
+ else
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"egl >= 1.5\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "egl >= 1.5") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_EGL_CFLAGS=`$PKG_CONFIG --cflags "egl >= 1.5" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ fi
+else
+ pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+ if test -n "$EGL_LIBS"; then
+ pkg_cv_EGL_LIBS="$EGL_LIBS"
+ else
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"egl >= 1.5\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "egl >= 1.5") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_EGL_LIBS=`$PKG_CONFIG --libs "egl >= 1.5" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ fi
+else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ EGL_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "egl >= 1.5"`
+ else
+ EGL_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "egl >= 1.5"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$EGL_PKG_ERRORS" >&5
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: EGL 1.5+ not available. Will use GLX." >&5
+$as_echo "$as_me: EGL 1.5+ not available. Will use GLX." >&6;}
+
+
+elif test $pkg_failed = untried; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: EGL 1.5+ not available. Will use GLX." >&5
+$as_echo "$as_me: EGL 1.5+ not available. Will use GLX." >&6;}
+
+
+else
+ EGL_CFLAGS=$pkg_cv_EGL_CFLAGS
+ EGL_LIBS=$pkg_cv_EGL_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+ OPENGL_LIBS="$OPENGL_LIBS $EGL_LIBS"
+ $as_echo "#define wxUSE_GLCANVAS_EGL 1" >>confdefs.h
+
+
+fi
+ fi
fi
fi
diff --git a/configure.in b/configure.in
index 37622d6d51..fd7d7d9caf 100644
--- a/configure.in
+++ b/configure.in
@@ -3793,6 +3793,18 @@ if test "$wxUSE_OPENGL" = "yes" -o "$wxUSE_OPENGL" = "auto"; then
found_gl=1
OPENGL_LIBS="-lGL -lGLU"
+
+ if test "$WXGTK3" = 1; then
+ PKG_CHECK_MODULES(EGL, [egl >= 1.5],
+ [
+ OPENGL_LIBS="$OPENGL_LIBS $EGL_LIBS"
+ AC_DEFINE(wxUSE_GLCANVAS_EGL)
+ ],
+ [
+ AC_MSG_NOTICE([EGL 1.5+ not available. Will use GLX.])
+ ]
+ )
+ fi
fi
fi
diff --git a/include/wx/android/setup.h b/include/wx/android/setup.h
index 197a0af802..fcf2d989d2 100644
--- a/include/wx/android/setup.h
+++ b/include/wx/android/setup.h
@@ -1386,6 +1386,13 @@
// otherwise.
#define wxUSE_GLCANVAS 1
+// Setting wxUSE_GLCANVAS_EGL to 1 enables OpenGL EGL backend. This will be
+// automatically enabled if EGL support is detected.
+//
+// Default is 0.
+//
+#define wxUSE_GLCANVAS_EGL 0
+
// wxRichTextCtrl allows editing of styled text.
//
// Default is 1.
diff --git a/include/wx/gtk/glcanvas.h b/include/wx/gtk/glcanvas.h
index ff0eddd141..a4aaffb9ad 100644
--- a/include/wx/gtk/glcanvas.h
+++ b/include/wx/gtk/glcanvas.h
@@ -11,15 +11,23 @@
#ifndef _WX_GLCANVAS_H_
#define _WX_GLCANVAS_H_
-#include "wx/unix/glx11.h"
+#include "wx/setup.h"
+
+#if wxUSE_GLCANVAS_EGL
+ #include "wx/unix/glegl.h"
+ typedef wxGLCanvasEGL wxGLCanvasImpl;
+#else
+ #include "wx/unix/glx11.h"
+ typedef wxGLCanvasX11 wxGLCanvasImpl;
+#endif
//---------------------------------------------------------------------------
// wxGLCanvas
//---------------------------------------------------------------------------
-class WXDLLIMPEXP_GL wxGLCanvas : public wxGLCanvasX11
+class WXDLLIMPEXP_GL wxGLCanvas : public wxGLCanvasImpl
{
- typedef wxGLCanvasX11 BaseType;
+ typedef wxGLCanvasImpl BaseType;
public:
wxGLCanvas(wxWindow *parent,
const wxGLAttributes& dispAttrs,
@@ -64,7 +72,7 @@ public:
// --------------------------------
virtual unsigned long GetXWindow() const wxOVERRIDE;
-
+ void* GetNativeWindow() const;
// deprecated methods
// ------------------
diff --git a/include/wx/gtk/setup0.h b/include/wx/gtk/setup0.h
index e09a86bfdf..1a8dc8f40a 100644
--- a/include/wx/gtk/setup0.h
+++ b/include/wx/gtk/setup0.h
@@ -1387,6 +1387,13 @@
// otherwise.
#define wxUSE_GLCANVAS 1
+// Setting wxUSE_GLCANVAS_EGL to 1 enables OpenGL EGL backend. This will be
+// automatically enabled if EGL support is detected.
+//
+// Default is 0.
+//
+#define wxUSE_GLCANVAS_EGL 0
+
// wxRichTextCtrl allows editing of styled text.
//
// Default is 1.
diff --git a/include/wx/motif/setup0.h b/include/wx/motif/setup0.h
index cf7268d1a5..1fb42dca02 100644
--- a/include/wx/motif/setup0.h
+++ b/include/wx/motif/setup0.h
@@ -1387,6 +1387,13 @@
// otherwise.
#define wxUSE_GLCANVAS 1
+// Setting wxUSE_GLCANVAS_EGL to 1 enables OpenGL EGL backend. This will be
+// automatically enabled if EGL support is detected.
+//
+// Default is 0.
+//
+#define wxUSE_GLCANVAS_EGL 0
+
// wxRichTextCtrl allows editing of styled text.
//
// Default is 1.
diff --git a/include/wx/msw/setup0.h b/include/wx/msw/setup0.h
index 0905003ab1..e253cc3cbd 100644
--- a/include/wx/msw/setup0.h
+++ b/include/wx/msw/setup0.h
@@ -1387,6 +1387,13 @@
// otherwise.
#define wxUSE_GLCANVAS 1
+// Setting wxUSE_GLCANVAS_EGL to 1 enables OpenGL EGL backend. This will be
+// automatically enabled if EGL support is detected.
+//
+// Default is 0.
+//
+#define wxUSE_GLCANVAS_EGL 0
+
// wxRichTextCtrl allows editing of styled text.
//
// Default is 1.
diff --git a/include/wx/osx/setup0.h b/include/wx/osx/setup0.h
index 04636ec158..a5ff4f93c7 100644
--- a/include/wx/osx/setup0.h
+++ b/include/wx/osx/setup0.h
@@ -1393,6 +1393,13 @@
// otherwise.
#define wxUSE_GLCANVAS 1
+// Setting wxUSE_GLCANVAS_EGL to 1 enables OpenGL EGL backend. This will be
+// automatically enabled if EGL support is detected.
+//
+// Default is 0.
+//
+#define wxUSE_GLCANVAS_EGL 0
+
// wxRichTextCtrl allows editing of styled text.
//
// Default is 1.
diff --git a/include/wx/setup_inc.h b/include/wx/setup_inc.h
index 623ed70752..c24b0abf48 100644
--- a/include/wx/setup_inc.h
+++ b/include/wx/setup_inc.h
@@ -1383,6 +1383,14 @@
// otherwise.
#define wxUSE_GLCANVAS 1
+// Setting wxUSE_GLCANVAS_EGL to 1 enables OpenGL EGL backend. This will be
+// automatically enabled if EGL support is detected. EGL support is only
+// available under Unix platforms.
+//
+// Default is 0.
+//
+#define wxUSE_GLCANVAS_EGL 0
+
// wxRichTextCtrl allows editing of styled text.
//
// Default is 1.
diff --git a/include/wx/univ/setup0.h b/include/wx/univ/setup0.h
index a8ab9b665f..a7eee09ad7 100644
--- a/include/wx/univ/setup0.h
+++ b/include/wx/univ/setup0.h
@@ -1386,6 +1386,13 @@
// otherwise.
#define wxUSE_GLCANVAS 1
+// Setting wxUSE_GLCANVAS_EGL to 1 enables OpenGL EGL backend. This will be
+// automatically enabled if EGL support is detected.
+//
+// Default is 0.
+//
+#define wxUSE_GLCANVAS_EGL 0
+
// wxRichTextCtrl allows editing of styled text.
//
// Default is 1.
diff --git a/include/wx/unix/glegl.h b/include/wx/unix/glegl.h
new file mode 100644
index 0000000000..ccdd302e36
--- /dev/null
+++ b/include/wx/unix/glegl.h
@@ -0,0 +1,179 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/unix/glegl.h
+// Purpose: class common for all EGL-based wxGLCanvas implementations
+// Author: Scott Talbert
+// Created: 2017-12-26
+// Copyright: (c) 2017 Scott Talbert
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_UNIX_GLEGL_H_
+#define _WX_UNIX_GLEGL_H_
+
+#include
+
+// This is to avoid including Wayland & EGL headers here to pollute namespace
+struct wl_compositor;
+struct wl_subcompositor;
+struct wl_callback;
+struct wl_egl_window;
+struct wl_surface;
+struct wl_region;
+struct wl_subsurface;
+typedef void *EGLDisplay;
+typedef void *EGLConfig;
+typedef void *EGLSurface;
+typedef void *EGLContext;
+
+class wxGLContextAttrs;
+class wxGLAttributes;
+
+// ----------------------------------------------------------------------------
+// wxGLContext
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_GL wxGLContext : public wxGLContextBase
+{
+public:
+ wxGLContext(wxGLCanvas *win,
+ const wxGLContext *other = NULL,
+ const wxGLContextAttrs *ctxAttrs = NULL);
+ virtual ~wxGLContext();
+
+ virtual bool SetCurrent(const wxGLCanvas& win) const wxOVERRIDE;
+
+private:
+ EGLContext m_glContext;
+
+ wxDECLARE_CLASS(wxGLContext);
+};
+
+// ----------------------------------------------------------------------------
+// wxGLCanvasEGL
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_GL wxGLCanvasEGL : public wxGLCanvasBase
+{
+public:
+ // initialization and dtor
+ // -----------------------
+
+ // default ctor doesn't do anything, InitConfig() must be called
+ wxGLCanvasEGL();
+
+ // initializes EGLConfig corresponding to the given attributes
+ bool InitVisual(const wxGLAttributes& dispAttrs);
+
+ // creates EGLSurface
+ bool CreateSurface();
+
+ virtual ~wxGLCanvasEGL();
+
+
+ // implement wxGLCanvasBase methods
+ // --------------------------------
+
+ virtual bool SwapBuffers() wxOVERRIDE;
+
+
+ // X11-specific methods
+ // --------------------
+
+ // get the X11 handle of this window
+ virtual unsigned long GetXWindow() const = 0;
+
+
+ // override some wxWindow methods
+ // ------------------------------
+
+ // return true only if the window is realized: OpenGL context can't be
+ // created until we are
+ virtual bool IsShownOnScreen() const wxOVERRIDE;
+
+
+ // implementation only from now on
+ // -------------------------------
+
+ // get the EGLConfig we use
+ EGLConfig *GetEGLConfig() const { return m_config; }
+ EGLDisplay GetEGLDisplay() const { return m_display; }
+ EGLSurface GetEGLSurface() const { return m_surface; }
+
+ static EGLDisplay GetDisplay();
+
+ // initialize the global default GL config, return false if matching config
+ // not found
+ static bool InitDefaultConfig(const int *attribList);
+
+ // get the default EGL Config (may be NULL, shouldn't be freed by caller)
+ static EGLConfig *GetDefaultConfig() { return ms_glEGLConfig; }
+
+ // free the global GL visual, called by wxGLApp
+ static void FreeDefaultConfig();
+
+ // initializes EGLConfig
+ //
+ // returns NULL if EGLConfig couldn't be initialized, otherwise caller
+ // is responsible for freeing the pointer
+ static EGLConfig *InitConfig(const wxGLAttributes& dispAttrs);
+
+ bool m_readyToDraw;
+ wl_compositor *m_wlCompositor;
+ wl_subcompositor *m_wlSubcompositor;
+ wl_callback *m_wlFrameCallbackHandler;
+ wl_egl_window *m_wlEGLWindow;
+
+private:
+
+ EGLConfig *m_config;
+ EGLDisplay m_display;
+ EGLSurface m_surface;
+
+ unsigned long m_xwindow;
+ wl_surface *m_wlSurface;
+ wl_region *m_wlRegion;
+ wl_subsurface *m_wlSubsurface;
+
+ // the global/default versions of the above
+ static EGLConfig *ms_glEGLConfig;
+};
+
+// ----------------------------------------------------------------------------
+// wxGLApp
+// ----------------------------------------------------------------------------
+
+// this is used in wx/glcanvas.h, prevent it from defining a generic wxGLApp
+#define wxGL_APP_DEFINED
+
+class WXDLLIMPEXP_GL wxGLApp : public wxGLAppBase
+{
+public:
+ wxGLApp() : wxGLAppBase() { }
+
+ // implement wxGLAppBase method
+ virtual bool InitGLVisual(const int *attribList) wxOVERRIDE
+ {
+ return wxGLCanvasEGL::InitDefaultConfig(attribList);
+ }
+
+ // This method is not currently used by the library itself, but remains for
+ // backwards compatibility and also because wxGTK has it we could start
+ // using it for the same purpose in wxX11 too some day.
+ virtual void* GetXVisualInfo() wxOVERRIDE
+ {
+ return wxGLCanvasEGL::GetDefaultConfig();
+ }
+
+ // and override this wxApp method to clean up
+ virtual int OnExit() wxOVERRIDE
+ {
+ wxGLCanvasEGL::FreeDefaultConfig();
+
+ return wxGLAppBase::OnExit();
+ }
+
+private:
+ wxDECLARE_DYNAMIC_CLASS(wxGLApp);
+};
+
+#endif // _WX_UNIX_GLEGL_H_
diff --git a/include/wx/utils.h b/include/wx/utils.h
index 1ac67eeff8..c6d35299c2 100644
--- a/include/wx/utils.h
+++ b/include/wx/utils.h
@@ -780,6 +780,18 @@ void WXDLLIMPEXP_CORE wxGetMousePosition( int* x, int* y );
#ifdef __WXGTK__
WXDLLIMPEXP_CORE void *wxGetDisplay();
+ enum wxDisplayType
+ {
+ wxDisplayNone,
+ wxDisplayX11,
+ wxDisplayWayland
+ };
+ struct wxDisplayInfo
+ {
+ void* dpy;
+ wxDisplayType type;
+ };
+ WXDLLIMPEXP_CORE wxDisplayInfo wxGetDisplayInfo();
#endif
#ifdef __X__
diff --git a/setup.h.in b/setup.h.in
index b724a18cbe..47fa4e5a02 100644
--- a/setup.h.in
+++ b/setup.h.in
@@ -549,6 +549,8 @@
#define wxUSE_GLCANVAS 0
+#define wxUSE_GLCANVAS_EGL 0
+
#define wxUSE_RICHTEXT 0
diff --git a/src/gtk/glcanvas.cpp b/src/gtk/glcanvas.cpp
index 67c7c50f73..4c63a82450 100644
--- a/src/gtk/glcanvas.cpp
+++ b/src/gtk/glcanvas.cpp
@@ -16,7 +16,12 @@
#include "wx/glcanvas.h"
#include "wx/gtk/private/wrapgtk.h"
+#ifdef GDK_WINDOWING_WAYLAND
+#include
+#endif
+#ifdef GDK_WINDOWING_X11
#include
+#endif
#ifdef __WXGTK3__
extern "C" {
@@ -43,6 +48,7 @@ static gboolean draw(GtkWidget* widget, cairo_t* cr, wxGLCanvas* win)
// emission hook for "parent-set"
//-----------------------------------------------------------------------------
+#if !wxUSE_GLCANVAS_EGL
extern "C" {
static gboolean
parent_set_hook(GSignalInvocationHint*, guint, const GValue* param_values, void* data)
@@ -70,6 +76,7 @@ parent_set_hook(GSignalInvocationHint*, guint, const GValue* param_values, void*
return true;
}
}
+#endif
//---------------------------------------------------------------------------
// wxGlCanvas
@@ -160,15 +167,25 @@ wxGLCanvas::wxGLCanvas(wxWindow *parent,
static bool IsAvailable()
{
-#ifdef GDK_WINDOWING_X11
- if ( !GDK_IS_X11_DISPLAY(gdk_display_get_default()) )
-#endif
+#ifdef GDK_WINDOWING_WAYLAND
+ if ( GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default()) )
{
- wxSafeShowMessage(_("Fatal Error"), _("wxGLCanvas is only supported on X11 currently. You may be able to\nwork around this by setting environment variable GDK_BACKEND=x11 before starting\nyour program."));
+#if wxUSE_GLCANVAS_EGL
+ return true;
+#else
+ wxSafeShowMessage(_("Fatal Error"), _("This program wasn't compiled with EGL support required under Wayland, either\ninstall EGL libraries and rebuild or run it under X11 backend by setting\nenvironment variable GDK_BACKEND=x11 before starting your program."));
return false;
+#endif // wxUSE_GLCANVAS_EGL
}
+#endif // GDK_WINDOWING_WAYLAND
- return true;
+#ifdef GDK_WINDOWING_X11
+ if ( GDK_IS_X11_DISPLAY(gdk_display_get_default()) )
+ return true;
+#endif
+
+ wxSafeShowMessage(_("Fatal Error"), _("wxGLCanvas is only supported on Wayland and X11 currently. You may be able to\nwork around this by setting environment variable GDK_BACKEND=x11 before\nstarting your program."));
+ return false;
}
bool wxGLCanvas::Create(wxWindow *parent,
@@ -221,8 +238,10 @@ bool wxGLCanvas::Create(wxWindow *parent,
// watch for the "parent-set" signal on m_wxwindow so we can set colormap
// before m_wxwindow is realized (which will occur before
// wxWindow::Create() returns if parent is already visible)
+#if !wxUSE_GLCANVAS_EGL
unsigned sig_id = g_signal_lookup("parent-set", GTK_TYPE_WIDGET);
g_signal_add_emission_hook(sig_id, 0, parent_set_hook, this, NULL);
+#endif
wxWindow::Create( parent, id, pos, size, style, name );
#ifdef __WXGTK3__
@@ -251,6 +270,9 @@ void wxGLCanvas::GTKHandleRealized()
#if WXWIN_COMPATIBILITY_2_8
GTKInitImplicitContext();
+#endif
+#if wxUSE_GLCANVAS_EGL
+ CreateSurface();
#endif
SendSizeEvent();
}
diff --git a/src/gtk/utilsgtk.cpp b/src/gtk/utilsgtk.cpp
index 4a7afc9edc..6dc15e1a2d 100644
--- a/src/gtk/utilsgtk.cpp
+++ b/src/gtk/utilsgtk.cpp
@@ -26,6 +26,9 @@
#include "wx/evtloop.h"
#include "wx/gtk/private/wrapgtk.h"
+#ifdef GDK_WINDOWING_WAYLAND
+#include
+#endif
#ifdef GDK_WINDOWING_WIN32
#include
#endif
@@ -69,12 +72,31 @@ void wxBell()
// display characteristics
// ----------------------------------------------------------------------------
-#ifdef GDK_WINDOWING_X11
void *wxGetDisplay()
{
- return GDK_DISPLAY_XDISPLAY(gdk_window_get_display(wxGetTopLevelGDK()));
+ return wxGetDisplayInfo().dpy;
}
+
+wxDisplayInfo wxGetDisplayInfo()
+{
+ wxDisplayInfo info = { NULL, wxDisplayNone };
+ GdkDisplay *display = gdk_window_get_display(wxGetTopLevelGDK());
+#ifdef GDK_WINDOWING_X11
+ if (GDK_IS_X11_DISPLAY(display)) {
+ info.dpy = GDK_DISPLAY_XDISPLAY(display);
+ info.type = wxDisplayX11;
+ return info;
+ }
#endif
+#ifdef GDK_WINDOWING_WAYLAND
+ if (GDK_IS_WAYLAND_DISPLAY(display)) {
+ info.dpy = gdk_wayland_display_get_wl_display(display);
+ info.type = wxDisplayWayland;
+ return info;
+ }
+#endif
+ return info;
+}
wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
{
diff --git a/src/unix/glegl.cpp b/src/unix/glegl.cpp
new file mode 100644
index 0000000000..e79ad23792
--- /dev/null
+++ b/src/unix/glegl.cpp
@@ -0,0 +1,654 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: src/unix/glegl.cpp
+// Purpose: code common to all EGL-based wxGLCanvas implementations
+// Author: Scott Talbert
+// Created: 2017-12-26
+// Copyright: (c) 2017 Scott Talbert
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if wxUSE_GLCANVAS && wxUSE_GLCANVAS_EGL
+
+#ifndef WX_PRECOMP
+ #include "wx/log.h"
+#endif //WX_PRECOMP
+
+#include "wx/glcanvas.h"
+
+#include
+#ifdef GDK_WINDOWING_WAYLAND
+#include
+#include
+#include
+#endif
+#ifdef GDK_WINDOWING_X11
+#include
+#endif
+
+#include
+#include
+
+// ----------------------------------------------------------------------------
+// wxGLContextAttrs: OpenGL rendering context attributes
+// ----------------------------------------------------------------------------
+// EGL specific values
+
+wxGLContextAttrs& wxGLContextAttrs::CoreProfile()
+{
+ AddAttribBits(EGL_CONTEXT_OPENGL_PROFILE_MASK,
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::MajorVersion(int val)
+{
+ if ( val > 0 )
+ {
+ AddAttribute(EGL_CONTEXT_MAJOR_VERSION);
+ AddAttribute(val);
+ }
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::MinorVersion(int val)
+{
+ if ( val >= 0 )
+ {
+ AddAttribute(EGL_CONTEXT_MINOR_VERSION);
+ AddAttribute(val);
+ }
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::CompatibilityProfile()
+{
+ AddAttribBits(EGL_CONTEXT_OPENGL_PROFILE_MASK,
+ EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::ForwardCompatible()
+{
+ AddAttribute(EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE);
+ AddAttribute(EGL_TRUE);
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::ES2()
+{
+ AddAttribBits(EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT);
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::DebugCtx()
+{
+ AddAttribute(EGL_CONTEXT_OPENGL_DEBUG);
+ AddAttribute(EGL_TRUE);
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::Robust()
+{
+ AddAttribute(EGL_CONTEXT_OPENGL_ROBUST_ACCESS);
+ AddAttribute(EGL_TRUE);
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::NoResetNotify()
+{
+ AddAttribute(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY);
+ AddAttribute(EGL_NO_RESET_NOTIFICATION);
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::LoseOnReset()
+{
+ AddAttribute(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY);
+ AddAttribute(EGL_LOSE_CONTEXT_ON_RESET);
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::ResetIsolation()
+{
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::ReleaseFlush(int)
+{
+ return *this;
+}
+
+wxGLContextAttrs& wxGLContextAttrs::PlatformDefaults()
+{
+ return *this;
+}
+
+void wxGLContextAttrs::EndList()
+{
+ AddAttribute(EGL_NONE);
+}
+
+// ----------------------------------------------------------------------------
+// wxGLAttributes: Visual/FBconfig attributes
+// ----------------------------------------------------------------------------
+
+wxGLAttributes& wxGLAttributes::RGBA()
+{
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::BufferSize(int val)
+{
+ if ( val >= 0 )
+ {
+ AddAttribute(EGL_BUFFER_SIZE);
+ AddAttribute(val);
+ }
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::Level(int val)
+{
+ AddAttribute(EGL_LEVEL);
+ AddAttribute(val);
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::DoubleBuffer()
+{
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::Stereo()
+{
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::AuxBuffers(int)
+{
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::MinRGBA(int mRed, int mGreen, int mBlue, int mAlpha)
+{
+ if ( mRed >= 0)
+ {
+ AddAttribute(EGL_RED_SIZE);
+ AddAttribute(mRed);
+ }
+ if ( mGreen >= 0)
+ {
+ AddAttribute(EGL_GREEN_SIZE);
+ AddAttribute(mGreen);
+ }
+ if ( mBlue >= 0)
+ {
+ AddAttribute(EGL_BLUE_SIZE);
+ AddAttribute(mBlue);
+ }
+ if ( mAlpha >= 0)
+ {
+ AddAttribute(EGL_ALPHA_SIZE);
+ AddAttribute(mAlpha);
+ }
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::Depth(int val)
+{
+ if ( val >= 0 )
+ {
+ AddAttribute(EGL_DEPTH_SIZE);
+ AddAttribute(val);
+ }
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::Stencil(int val)
+{
+ if ( val >= 0 )
+ {
+ AddAttribute(EGL_STENCIL_SIZE);
+ AddAttribute(val);
+ }
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::MinAcumRGBA(int, int, int, int)
+{
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::SampleBuffers(int val)
+{
+ if ( val >= 0 )
+ {
+ AddAttribute(EGL_SAMPLE_BUFFERS);
+ AddAttribute(val);
+ }
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::Samplers(int val)
+{
+ if ( val >= 0 )
+ {
+ AddAttribute(EGL_SAMPLES);
+ AddAttribute(val);
+ }
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::FrameBuffersRGB()
+{
+ return *this;
+}
+
+void wxGLAttributes::EndList()
+{
+ AddAttribute(EGL_NONE);
+}
+
+wxGLAttributes& wxGLAttributes::PlatformDefaults()
+{
+ // No EGL specific values
+ return *this;
+}
+
+wxGLAttributes& wxGLAttributes::Defaults()
+{
+ RGBA().DoubleBuffer().Depth(16).SampleBuffers(1).Samplers(4);
+ return *this;
+}
+
+void wxGLAttributes::AddDefaultsForWXBefore31()
+{
+ // ParseAttribList() will add EndList(), don't do it now
+ DoubleBuffer();
+}
+
+
+// ============================================================================
+// wxGLContext implementation
+// ============================================================================
+
+wxIMPLEMENT_CLASS(wxGLContext, wxObject);
+
+wxGLContext::wxGLContext(wxGLCanvas *win,
+ const wxGLContext *other,
+ const wxGLContextAttrs *ctxAttrs)
+ : m_glContext(NULL)
+{
+ const int* contextAttribs = NULL;
+
+ if ( ctxAttrs )
+ {
+ contextAttribs = ctxAttrs->GetGLAttrs();
+ }
+ else if ( win->GetGLCTXAttrs().GetGLAttrs() )
+ {
+ // If OpenGL context parameters were set at wxGLCanvas ctor, get them now
+ contextAttribs = win->GetGLCTXAttrs().GetGLAttrs();
+ }
+
+ m_isOk = false;
+
+ EGLConfig *fbc = win->GetEGLConfig();
+ wxCHECK_RET( fbc, "Invalid EGLConfig for OpenGL" );
+
+ m_glContext = eglCreateContext(wxGLCanvasEGL::GetDisplay(), fbc[0],
+ other ? other->m_glContext : EGL_NO_CONTEXT,
+ contextAttribs);
+
+ if ( !m_glContext )
+ wxLogMessage(_("Couldn't create OpenGL context"));
+ else
+ m_isOk = true;
+}
+
+wxGLContext::~wxGLContext()
+{
+ if ( !m_glContext )
+ return;
+
+ if ( m_glContext == eglGetCurrentContext() )
+ eglMakeCurrent(wxGLCanvasEGL::GetDisplay(), EGL_NO_SURFACE,
+ EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+ eglDestroyContext(wxGLCanvasEGL::GetDisplay(), m_glContext);
+}
+
+bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
+{
+ if ( !m_glContext )
+ return false;
+
+ return eglMakeCurrent(win.GetEGLDisplay(), win.GetEGLSurface(),
+ win.GetEGLSurface(), m_glContext);
+}
+
+// ============================================================================
+// wxGLCanvasEGL implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// initialization methods and dtor
+// ----------------------------------------------------------------------------
+
+wxGLCanvasEGL::wxGLCanvasEGL()
+{
+ m_config = NULL;
+ m_display = NULL;
+ m_surface = EGL_NO_SURFACE;
+ m_wlCompositor = NULL;
+ m_wlSubcompositor = NULL;
+ m_wlFrameCallbackHandler = NULL;
+ m_wlEGLWindow = NULL;
+ m_wlSurface = NULL;
+ m_wlRegion = NULL;
+ m_wlSubsurface = NULL;
+ m_readyToDraw = false;
+}
+
+bool wxGLCanvasEGL::InitVisual(const wxGLAttributes& dispAttrs)
+{
+ m_config = InitConfig(dispAttrs);
+ if ( !m_config )
+ {
+ wxFAIL_MSG("Failed to get an EGLConfig for the requested attributes.");
+ }
+ return m_config != NULL;
+}
+
+/* static */
+EGLDisplay wxGLCanvasEGL::GetDisplay()
+{
+ wxDisplayInfo info = wxGetDisplayInfo();
+ EGLenum platform;
+ switch ( info.type )
+ {
+ case wxDisplayX11:
+ platform = EGL_PLATFORM_X11_EXT;
+ break;
+ case wxDisplayWayland:
+ platform = EGL_PLATFORM_WAYLAND_EXT;
+ break;
+ default:
+ return EGL_NO_DISPLAY;
+ }
+
+ return eglGetPlatformDisplay(platform, info.dpy, NULL);
+}
+
+extern "C"
+{
+
+static void wl_global (void *data,
+ struct wl_registry *wl_registry,
+ uint32_t name,
+ const char *interface,
+ uint32_t)
+{
+ wxGLCanvasEGL *glc = static_cast(data);
+
+ if ( !strcmp (interface, "wl_compositor") )
+ glc->m_wlCompositor = (struct wl_compositor *) wl_registry_bind (wl_registry, name, &wl_compositor_interface, 3);
+ else if ( !strcmp (interface, "wl_subcompositor") )
+ glc->m_wlSubcompositor = (struct wl_subcompositor *) wl_registry_bind (wl_registry, name, &wl_subcompositor_interface, 1);
+}
+
+static void wl_global_remove (void *,
+ struct wl_registry *,
+ uint32_t)
+{
+}
+
+static const struct wl_registry_listener wl_registry_listener = {
+ wl_global,
+ wl_global_remove
+};
+
+static void wl_frame_callback_handler(void* data,
+ struct wl_callback *,
+ uint32_t)
+{
+ wxGLCanvasEGL *glc = static_cast(data);
+ glc->m_readyToDraw = true;
+ g_clear_pointer(&glc->m_wlFrameCallbackHandler, wl_callback_destroy);
+ glc->SendSizeEvent();
+ gtk_widget_queue_draw(glc->m_wxwindow);
+}
+
+static const struct wl_callback_listener wl_frame_listener = {
+ wl_frame_callback_handler
+};
+
+static void gtk_glcanvas_size_callback(GtkWidget *widget,
+ GtkAllocation *,
+ wxGLCanvasEGL *win)
+{
+ int scale = gtk_widget_get_scale_factor(widget);
+ wl_egl_window_resize(win->m_wlEGLWindow, win->m_width * scale,
+ win->m_height * scale, 0, 0);
+}
+
+} // extern "C"
+
+bool wxGLCanvasEGL::CreateSurface()
+{
+ m_display = GetDisplay();
+ if ( m_display == EGL_NO_DISPLAY )
+ {
+ wxFAIL_MSG("Unable to get EGL Display");
+ return false;
+ }
+
+ GdkWindow *window = GTKGetDrawingWindow();
+#ifdef GDK_WINDOWING_X11
+ if ( GDK_IS_X11_WINDOW(window) )
+ {
+ m_xwindow = GDK_WINDOW_XID(window);
+ m_surface = eglCreatePlatformWindowSurface(m_display, *m_config,
+ &m_xwindow, NULL);
+ m_readyToDraw = true;
+ }
+#endif
+#ifdef GDK_WINDOWING_WAYLAND
+ if ( GDK_IS_WAYLAND_WINDOW(window) )
+ {
+ int x, y;
+ gdk_window_get_origin(window, &x, &y);
+ int w = gdk_window_get_width(window);
+ int h = gdk_window_get_height(window);
+ struct wl_display *display = gdk_wayland_display_get_wl_display(gdk_window_get_display(window));
+ struct wl_surface *surface = gdk_wayland_window_get_wl_surface(window);
+ struct wl_registry *registry = wl_display_get_registry(display);
+ wl_registry_add_listener(registry, &wl_registry_listener, this);
+ wl_display_roundtrip(display);
+ if ( !m_wlCompositor || !m_wlSubcompositor )
+ {
+ wxFAIL_MSG("Invalid Wayland compositor or subcompositor");
+ return false;
+ }
+ m_wlSurface = wl_compositor_create_surface(m_wlCompositor);
+ m_wlRegion = wl_compositor_create_region(m_wlCompositor);
+ m_wlSubsurface = wl_subcompositor_get_subsurface(m_wlSubcompositor,
+ m_wlSurface,
+ surface);
+ wl_surface_set_input_region(m_wlSurface, m_wlRegion);
+ wl_subsurface_set_desync(m_wlSubsurface);
+ wl_subsurface_set_position(m_wlSubsurface, x, y);
+ int scale = gdk_window_get_scale_factor(window);
+ wl_surface_set_buffer_scale(m_wlSurface, scale);
+ m_wlEGLWindow = wl_egl_window_create(m_wlSurface, w * scale,
+ h * scale);
+ m_surface = eglCreatePlatformWindowSurface(m_display, *m_config,
+ m_wlEGLWindow, NULL);
+ m_wlFrameCallbackHandler = wl_surface_frame(surface);
+ wl_callback_add_listener(m_wlFrameCallbackHandler,
+ &wl_frame_listener, this);
+ g_signal_connect(m_widget, "size-allocate",
+ G_CALLBACK(gtk_glcanvas_size_callback), this);
+ }
+#endif
+
+ if ( m_surface == EGL_NO_SURFACE )
+ {
+ wxFAIL_MSG("Unable to create EGL surface");
+ return false;
+ }
+
+ return true;
+}
+
+wxGLCanvasEGL::~wxGLCanvasEGL()
+{
+ if ( m_config && m_config != ms_glEGLConfig )
+ delete m_config;
+ if ( m_surface )
+ eglDestroySurface(m_display, m_surface);
+ g_clear_pointer(&m_wlEGLWindow, wl_egl_window_destroy);
+ g_clear_pointer(&m_wlSubsurface, wl_subsurface_destroy);
+ g_clear_pointer(&m_wlSurface, wl_surface_destroy);
+ g_clear_pointer(&m_wlFrameCallbackHandler, wl_callback_destroy);
+}
+
+// ----------------------------------------------------------------------------
+// working with GL attributes
+// ----------------------------------------------------------------------------
+
+/* static */
+bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
+{
+ EGLDisplay dpy = eglGetDisplay(static_cast(wxGetDisplay()));
+
+ return IsExtensionInList(eglQueryString(dpy, EGL_EXTENSIONS), extension);
+}
+
+
+/* static */
+EGLConfig *wxGLCanvasEGL::InitConfig(const wxGLAttributes& dispAttrs)
+{
+ const int* attrsList = dispAttrs.GetGLAttrs();
+ if ( !attrsList )
+ {
+ wxFAIL_MSG("wxGLAttributes object is empty.");
+ return NULL;
+ }
+
+ EGLDisplay dpy = GetDisplay();
+ if ( dpy == EGL_NO_DISPLAY ) {
+ wxFAIL_MSG("Unable to get EGL Display");
+ return NULL;
+ }
+ if ( !eglInitialize(dpy, NULL, NULL) )
+ {
+ wxFAIL_MSG("eglInitialize failed");
+ return NULL;
+ }
+ if ( !eglBindAPI(EGL_OPENGL_API) ) {
+ wxFAIL_MSG("eglBindAPI failed");
+ return NULL;
+ }
+
+ EGLConfig *config = new EGLConfig;
+ int returned;
+ // Use the first good match
+ if ( eglChooseConfig(dpy, attrsList, config, 1, &returned) && returned == 1 )
+ {
+ return config;
+ }
+ else
+ {
+ wxFAIL_MSG("eglChooseConfig failed");
+ delete config;
+ return NULL;
+ }
+}
+
+/* static */
+bool wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs)
+{
+ wxScopedPtr config(wxGLCanvasEGL::InitConfig(dispAttrs));
+ return config != NULL;
+}
+
+/* static */
+bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
+{
+ wxGLAttributes dispAttrs;
+ ParseAttribList(attribList, dispAttrs);
+
+ return IsDisplaySupported(dispAttrs);
+}
+
+// ----------------------------------------------------------------------------
+// default visual management
+// ----------------------------------------------------------------------------
+
+EGLConfig *wxGLCanvasEGL::ms_glEGLConfig = NULL;
+
+/* static */
+bool wxGLCanvasEGL::InitDefaultConfig(const int *attribList)
+{
+ FreeDefaultConfig();
+ wxGLAttributes dispAttrs;
+ ParseAttribList(attribList, dispAttrs);
+
+ ms_glEGLConfig = InitConfig(dispAttrs);
+ return ms_glEGLConfig != NULL;
+}
+
+/* static */
+void wxGLCanvasEGL::FreeDefaultConfig()
+{
+ if ( ms_glEGLConfig )
+ {
+ delete ms_glEGLConfig;
+ ms_glEGLConfig = NULL;
+ }
+}
+
+// ----------------------------------------------------------------------------
+// other GL methods
+// ----------------------------------------------------------------------------
+
+bool wxGLCanvasEGL::SwapBuffers()
+{
+ // Under Wayland, if eglSwapBuffers() is called before the wl_surface has
+ // been realized, it will deadlock. Thus, we need to avoid swapping before
+ // this has happened.
+ if ( !m_readyToDraw )
+ return false;
+
+ return eglSwapBuffers(m_display, m_surface);
+}
+
+bool wxGLCanvasEGL::IsShownOnScreen() const
+{
+ wxDisplayInfo info = wxGetDisplayInfo();
+ switch ( info.type )
+ {
+ case wxDisplayX11:
+ return GetXWindow() && wxGLCanvasBase::IsShownOnScreen();
+ case wxDisplayWayland:
+ return m_readyToDraw && wxGLCanvasBase::IsShownOnScreen();
+ default:
+ return false;
+ }
+}
+
+#endif // wxUSE_GLCANVAS && wxUSE_GLCANVAS_EGL
+
diff --git a/src/unix/glx11.cpp b/src/unix/glx11.cpp
index e3f87feef8..b970db5762 100644
--- a/src/unix/glx11.cpp
+++ b/src/unix/glx11.cpp
@@ -18,7 +18,7 @@
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
-#if wxUSE_GLCANVAS
+#if wxUSE_GLCANVAS && !wxUSE_GLCANVAS_EGL
#ifndef WX_PRECOMP
#include "wx/log.h"