diff --git a/Makefile.in b/Makefile.in
index d228908e41..67aea962c8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -2630,13 +2630,14 @@ COND_PLATFORM_WIN32_1_GTK_PLATFORM_HDR = \
@COND_TOOLKIT_MSW@WEBVIEW_PLATFORM_HDR = \
@COND_TOOLKIT_MSW@ wx/msw/webviewhistoryitem_ie.h wx/msw/webview_ie.h \
@COND_TOOLKIT_MSW@ wx/msw/webview_edge.h
-@COND_TOOLKIT_GTK@OPENGL_PLATFORM_HDR = wx/unix/glx11.h \
-@COND_TOOLKIT_GTK@ wx/gtk/glcanvas.h wx/unix/glegl.h
+@COND_TOOLKIT_GTK@OPENGL_PLATFORM_HDR = wx/gtk/glcanvas.h \
+@COND_TOOLKIT_GTK@ wx/unix/glcanvas.h
@COND_TOOLKIT_MSW@OPENGL_PLATFORM_HDR = wx/msw/glcanvas.h
@COND_TOOLKIT_OSX_COCOA@OPENGL_PLATFORM_HDR = wx/osx/glcanvas.h
@COND_TOOLKIT_OSX_IPHONE@OPENGL_PLATFORM_HDR = wx/osx/glcanvas.h
@COND_TOOLKIT_QT@OPENGL_PLATFORM_HDR = wx/qt/glcanvas.h
-@COND_TOOLKIT_X11@OPENGL_PLATFORM_HDR = wx/unix/glx11.h wx/x11/glcanvas.h
+@COND_TOOLKIT_X11@OPENGL_PLATFORM_HDR = wx/x11/glcanvas.h \
+@COND_TOOLKIT_X11@ wx/unix/glcanvas.h
@COND_TOOLKIT_GTK_TOOLKIT_VERSION_2@AUI_PLATFORM_HDR = wx/aui/tabartgtk.h
@COND_TOOLKIT_MSW@AUI_PLATFORM_HDR = wx/aui/tabartmsw.h wx/aui/barartmsw.h
COND_PLATFORM_MACOSX_1_BASE_PLATFORM_HDR = \
@@ -12155,7 +12156,8 @@ 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_TOOLKIT_GTK@__OPENGL_PLATFORM_SRC_OBJECTS = \
-@COND_TOOLKIT_GTK@ gldll_glx11.o gldll_gtk_glcanvas.o gldll_glegl.o
+@COND_TOOLKIT_GTK@ gldll_glx11.o gldll_gtk_glcanvas.o gldll_glegl.o \
+@COND_TOOLKIT_GTK@ gldll_unix_glcanvas.o
@COND_TOOLKIT_MSW@__OPENGL_PLATFORM_SRC_OBJECTS = gldll_msw_glcanvas.o
@COND_TOOLKIT_OSX_COCOA@__OPENGL_PLATFORM_SRC_OBJECTS \
@COND_TOOLKIT_OSX_COCOA@ = gldll_glcanvas_osx.o gldll_cocoa_glcanvas.o
@@ -12163,7 +12165,7 @@ COND_USE_SOVERSOLARIS_1___gldll___so_symlinks_uninst_cmd = rm -f \
@COND_TOOLKIT_OSX_IPHONE@ = gldll_glcanvas_osx.o gldll_iphone_glcanvas.o
@COND_TOOLKIT_QT@__OPENGL_PLATFORM_SRC_OBJECTS = gldll_qt_glcanvas.o
@COND_TOOLKIT_X11@__OPENGL_PLATFORM_SRC_OBJECTS = \
-@COND_TOOLKIT_X11@ gldll_x11_glcanvas.o gldll_glx11.o
+@COND_TOOLKIT_X11@ gldll_x11_glcanvas.o gldll_glx11.o gldll_unix_glcanvas.o
COND_MONOLITHIC_0___WXLIBGLDEP_CORE_p = \
-lwx_$(PORTNAME)$(WXUNIVNAME)u$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR)_core-$(WX_RELEASE)$(HOST_SUFFIX)
@COND_MONOLITHIC_0@__WXLIBGLDEP_CORE_p = $(COND_MONOLITHIC_0___WXLIBGLDEP_CORE_p)
@@ -12186,7 +12188,8 @@ 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_TOOLKIT_GTK@__OPENGL_PLATFORM_SRC_OBJECTS_1 = \
-@COND_TOOLKIT_GTK@ gllib_glx11.o gllib_gtk_glcanvas.o gllib_glegl.o
+@COND_TOOLKIT_GTK@ gllib_glx11.o gllib_gtk_glcanvas.o gllib_glegl.o \
+@COND_TOOLKIT_GTK@ gllib_unix_glcanvas.o
@COND_TOOLKIT_MSW@__OPENGL_PLATFORM_SRC_OBJECTS_1 = gllib_msw_glcanvas.o
@COND_TOOLKIT_OSX_COCOA@__OPENGL_PLATFORM_SRC_OBJECTS_1 \
@COND_TOOLKIT_OSX_COCOA@ = gllib_glcanvas_osx.o gllib_cocoa_glcanvas.o
@@ -12194,7 +12197,7 @@ COND_SHARED_0_USE_GUI_1_USE_OPENGL_1___gllib___depname = \
@COND_TOOLKIT_OSX_IPHONE@ = gllib_glcanvas_osx.o gllib_iphone_glcanvas.o
@COND_TOOLKIT_QT@__OPENGL_PLATFORM_SRC_OBJECTS_1 = gllib_qt_glcanvas.o
@COND_TOOLKIT_X11@__OPENGL_PLATFORM_SRC_OBJECTS_1 = \
-@COND_TOOLKIT_X11@ gllib_x11_glcanvas.o gllib_glx11.o
+@COND_TOOLKIT_X11@ gllib_x11_glcanvas.o gllib_glx11.o gllib_unix_glcanvas.o
@COND_SHARED_1@____wxgl_namedll_DEP = $(__gldll___depname)
@COND_SHARED_0@____wxgl_namelib_DEP = $(__gllib___depname)
COND_WITH_PLUGIN_SDL_1___sound_sdl___depname = \
@@ -34418,6 +34421,12 @@ gldll_x11_glcanvas.o: $(srcdir)/src/x11/glcanvas.cpp $(GLDLL_ODEP)
@COND_TOOLKIT_X11@gldll_glx11.o: $(srcdir)/src/unix/glx11.cpp $(GLDLL_ODEP)
@COND_TOOLKIT_X11@ $(CXXC) -c -o $@ $(GLDLL_CXXFLAGS) $(srcdir)/src/unix/glx11.cpp
+@COND_TOOLKIT_GTK@gldll_unix_glcanvas.o: $(srcdir)/src/unix/glcanvas.cpp $(GLDLL_ODEP)
+@COND_TOOLKIT_GTK@ $(CXXC) -c -o $@ $(GLDLL_CXXFLAGS) $(srcdir)/src/unix/glcanvas.cpp
+
+@COND_TOOLKIT_X11@gldll_unix_glcanvas.o: $(srcdir)/src/unix/glcanvas.cpp $(GLDLL_ODEP)
+@COND_TOOLKIT_X11@ $(CXXC) -c -o $@ $(GLDLL_CXXFLAGS) $(srcdir)/src/unix/glcanvas.cpp
+
gllib_glcmn.o: $(srcdir)/src/common/glcmn.cpp $(GLLIB_ODEP)
$(CXXC) -c -o $@ $(GLLIB_CXXFLAGS) $(srcdir)/src/common/glcmn.cpp
@@ -34454,6 +34463,12 @@ gllib_x11_glcanvas.o: $(srcdir)/src/x11/glcanvas.cpp $(GLLIB_ODEP)
@COND_TOOLKIT_X11@gllib_glx11.o: $(srcdir)/src/unix/glx11.cpp $(GLLIB_ODEP)
@COND_TOOLKIT_X11@ $(CXXC) -c -o $@ $(GLLIB_CXXFLAGS) $(srcdir)/src/unix/glx11.cpp
+@COND_TOOLKIT_GTK@gllib_unix_glcanvas.o: $(srcdir)/src/unix/glcanvas.cpp $(GLLIB_ODEP)
+@COND_TOOLKIT_GTK@ $(CXXC) -c -o $@ $(GLLIB_CXXFLAGS) $(srcdir)/src/unix/glcanvas.cpp
+
+@COND_TOOLKIT_X11@gllib_unix_glcanvas.o: $(srcdir)/src/unix/glcanvas.cpp $(GLLIB_ODEP)
+@COND_TOOLKIT_X11@ $(CXXC) -c -o $@ $(GLLIB_CXXFLAGS) $(srcdir)/src/unix/glcanvas.cpp
+
sound_sdl_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp
$(CXXC) -c -o $@ $(SOUND_SDL_CXXFLAGS) $(srcdir)/src/unix/sound_sdl.cpp
diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl
index 3eea13d4a6..92e811a93c 100644
--- a/build/bakefiles/files.bkl
+++ b/build/bakefiles/files.bkl
@@ -2908,12 +2908,12 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
src/unix/glx11.cpp
src/gtk/glcanvas.cpp
src/unix/glegl.cpp
+ src/unix/glcanvas.cpp
- wx/unix/glx11.h
wx/gtk/glcanvas.h
- wx/unix/glegl.h
+ wx/unix/glcanvas.h
@@ -2937,11 +2937,12 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
src/x11/glcanvas.cpp
src/unix/glx11.cpp
+ src/unix/glcanvas.cpp
- wx/unix/glx11.h
wx/x11/glcanvas.h
+ wx/unix/glcanvas.h
diff --git a/build/cmake/files.cmake b/build/cmake/files.cmake
index 2a17698af5..b9584e6da8 100644
--- a/build/cmake/files.cmake
+++ b/build/cmake/files.cmake
@@ -2700,12 +2700,12 @@ set(OPENGL_GTK_SRC
src/gtk/glcanvas.cpp
src/unix/glx11.cpp
src/unix/glegl.cpp
+ src/unix/glcanvas.cpp
)
set(OPENGL_GTK_HDR
wx/gtk/glcanvas.h
- wx/unix/glx11.h
- wx/unix/glegl.h
+ wx/unix/glcanvas.h
)
set(OPENGL_OSX_COCOA_SRC
@@ -2729,11 +2729,12 @@ set(OPENGL_OSX_IPHONE_HDR
set(OPENGL_X11_SRC
src/x11/glcanvas.cpp
src/unix/glx11.cpp
+ src/unix/glcanvas.cpp
)
set(OPENGL_X11_HDR
wx/x11/glcanvas.h
- wx/unix/glx11.h
+ wx/unix/glcanvas.h
)
set(OPENGL_QT_SRC
diff --git a/build/cmake/init.cmake b/build/cmake/init.cmake
index ad2e6fa8ae..45a12ede07 100644
--- a/build/cmake/init.cmake
+++ b/build/cmake/init.cmake
@@ -537,6 +537,7 @@ if(wxUSE_GUI)
# library directly like this to avoid link problems.
set(OPENGL_LIBRARIES ${OPENGL_egl_LIBRARY} ${OPENGL_LIBRARIES})
endif()
+ set(wxHAS_EGL 1)
set(OPENGL_INCLUDE_DIR ${OPENGL_INCLUDE_DIR} ${OPENGL_EGL_INCLUDE_DIRS})
find_package(WAYLANDEGL)
if(WAYLANDEGL_FOUND AND wxHAVE_GDK_WAYLAND)
diff --git a/build/cmake/setup.h.in b/build/cmake/setup.h.in
index 1c09d7d0ca..4984e38aa3 100644
--- a/build/cmake/setup.h.in
+++ b/build/cmake/setup.h.in
@@ -497,8 +497,6 @@
#cmakedefine01 wxUSE_GLCANVAS
-#cmakedefine01 wxUSE_GLCANVAS_EGL
-
#cmakedefine01 wxUSE_RICHTEXT
@@ -1130,6 +1128,9 @@
/* Define if locale_t is available */
#cmakedefine HAVE_LOCALE_T 1
+/* Define if you have EGL support */
+#cmakedefine wxHAS_EGL 1
+
/* Define if you have inotify_xxx() functions. */
#cmakedefine wxHAS_INOTIFY 1
diff --git a/build/files b/build/files
index 52c7fc668f..55581da8e2 100644
--- a/build/files
+++ b/build/files
@@ -2668,13 +2668,13 @@ OPENGL_MSW_HDR =
OPENGL_GTK_SRC =
src/gtk/glcanvas.cpp
+ src/unix/glcanvas.cpp
src/unix/glegl.cpp
src/unix/glx11.cpp
OPENGL_GTK_HDR =
wx/gtk/glcanvas.h
- wx/unix/glegl.h
- wx/unix/glx11.h
+ wx/unix/glcanvas.h
OPENGL_OSX_COCOA_SRC =
src/osx/cocoa/glcanvas.mm
@@ -2691,11 +2691,12 @@ OPENGL_OSX_IPHONE_HDR =
wx/osx/glcanvas.h
OPENGL_X11_SRC =
+ src/unix/glcanvas.cpp
src/unix/glx11.cpp
src/x11/glcanvas.cpp
OPENGL_X11_HDR =
- wx/unix/glx11.h
+ wx/unix/glcanvas.h
wx/x11/glcanvas.h
OPENGL_QT_SRC =
diff --git a/configure b/configure
index 4f4659542f..683aab187a 100755
--- a/configure
+++ b/configure
@@ -1362,7 +1362,6 @@ enable_accessibility
enable_uiactionsim
enable_dctransform
enable_webviewwebkit
-enable_glcanvasegl
enable_palette
enable_image
enable_gif
@@ -2339,7 +2338,6 @@ Optional Features:
--enable-uiactionsim use wxUIActionSimulator
--enable-dctransform use wxDC::SetTransformMatrix and related
--enable-webviewwebkit use wxWebView WebKit backend
- --disable-glcanvasegl disable wxGLCanvas EGL backend
--enable-palette use wxPalette class
--enable-image use wxImage class
--enable-gif use gif images (GIF file format)
@@ -12374,35 +12372,6 @@ fi
eval "$wx_cv_use_webviewwebkit"
- enablestring=
- defaultval=$wxUSE_ALL_FEATURES
- if test -z "$defaultval"; then
- if test x"$enablestring" = xdisable; then
- defaultval=yes
- else
- defaultval=no
- fi
- fi
-
- # Check whether --enable-glcanvasegl was given.
-if test "${enable_glcanvasegl+set}" = set; then :
- enableval=$enable_glcanvasegl;
- if test "$enableval" = yes; then
- wx_cv_use_glcanvasegl='wxUSE_GLCANVAS_EGL=yes'
- else
- wx_cv_use_glcanvasegl='wxUSE_GLCANVAS_EGL=no'
- fi
-
-else
-
- wx_cv_use_glcanvasegl='wxUSE_GLCANVAS_EGL=${'DEFAULT_wxUSE_GLCANVAS_EGL":-$defaultval}"
-
-fi
-
-
- eval "$wx_cv_use_glcanvasegl"
-
-
enablestring=
@@ -31298,7 +31267,6 @@ fi
OPENGL_LIBS="-lGL"
if test "$WXGTK3" = 1; then
- if test "$wxUSE_GLCANVAS_EGL" != "no"; then
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egl >= 1.4" >&5
@@ -31359,7 +31327,7 @@ fi
echo "$EGL_PKG_ERRORS" >&5
- { $as_echo "$as_me:${as_lineno-$LINENO}: EGL 1.4+ not available. Will use GLX." >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: EGL 1.4+ not available. Will use GLX." >&5
$as_echo "$as_me: EGL 1.4+ not available. Will use GLX." >&6;}
@@ -31367,7 +31335,7 @@ elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: EGL 1.4+ not available. Will use GLX." >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: EGL 1.4+ not available. Will use GLX." >&5
$as_echo "$as_me: EGL 1.4+ not available. Will use GLX." >&6;}
@@ -31377,8 +31345,8 @@ else
{ $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
+ OPENGL_LIBS="$OPENGL_LIBS $EGL_LIBS"
+ $as_echo "#define wxHAS_EGL 1" >>confdefs.h
pkg_failed=no
@@ -31452,18 +31420,17 @@ else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- if test $wx_cv_gdk_wayland = "yes"; then
- OPENGL_LIBS="$OPENGL_LIBS $WAYLAND_EGL_LIBS"
- have_wayland=1
- fi
+ if test $wx_cv_gdk_wayland = "yes"; then
+ OPENGL_LIBS="$OPENGL_LIBS $WAYLAND_EGL_LIBS"
+ have_wayland=1
+ fi
fi
fi
- if test "$have_wayland" != 1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: wxGLCanvas will not have Wayland support" >&5
+ if test "$have_wayland" != 1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: wxGLCanvas will not have Wayland support" >&5
$as_echo "$as_me: wxGLCanvas will not have Wayland support" >&6;}
- fi
fi
fi
fi
diff --git a/configure.ac b/configure.ac
index b0d83d7e11..f92963e36d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3461,7 +3461,7 @@ if test "$wxUSE_OPENGL" = "yes" -o "$wxUSE_OPENGL" = "auto"; then
PKG_CHECK_MODULES(EGL, [egl >= 1.4],
[
OPENGL_LIBS="$OPENGL_LIBS $EGL_LIBS"
- AC_DEFINE(wxUSE_GLCANVAS_EGL)
+ AC_DEFINE(wxHAS_EGL)
PKG_CHECK_MODULES(WAYLAND_EGL, [wayland-egl],
[
if test $wx_cv_gdk_wayland = "yes"; then
diff --git a/docs/changes.txt b/docs/changes.txt
index d37c3d1538..a50bc6141a 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -237,6 +237,10 @@ Changes in behaviour which may result in build errors
previously compiled doesn't compile any longer, please fix it to use either
the ctor from RGB value or from string explicitly.
+- wxGLCanvas::CreateSurface() which was previously enabled in build
+ configurations using EGL is not available any longer as exposing it doesn't
+ make sense when wxGLCanvas may use either EGL or GLX.
+
3.3.2: (released 2025-??-??)
----------------------------
diff --git a/docs/doxygen/mainpages/const_cpp.h b/docs/doxygen/mainpages/const_cpp.h
index 849cdded8d..bcdc5b9b3f 100644
--- a/docs/doxygen/mainpages/const_cpp.h
+++ b/docs/doxygen/mainpages/const_cpp.h
@@ -187,6 +187,10 @@ Currently the following symbols exist:
ever, be necessary to use this symbol directly, functions such as
wxWindow::FromDIP() and wxBitmap::GetLogicalSize() exist to hide the
differences between the platforms with and without DPI-independent pixels.}
+@itemdef{wxHAS_EGL, Defined if wxGLCanvas may use EGL for OpenGL context
+ creation (this symbol only exists in wxWidgets 3.3.2 and later).}
+@itemdef{wxHAS_GLX, Defined if wxGLCanvas may use GLX for OpenGL context
+ creation (this symbol only exists in wxWidgets 3.3.2 and later).}
@itemdef{wxHAS_IMAGE_RESOURCES, Defined if wxICON() and wxBITMAP() macros use
images from (Windows) resources. Otherwise, these macros use XPMs.}
@itemdef{wxHAS_MEMBER_DEFAULT, Defined if the currently used compiler supports
diff --git a/include/wx/android/setup.h b/include/wx/android/setup.h
index 0e07c4343c..f683b11042 100644
--- a/include/wx/android/setup.h
+++ b/include/wx/android/setup.h
@@ -1321,14 +1321,6 @@
// 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/glcanvas.h b/include/wx/glcanvas.h
index a469b5421c..cdc4242470 100644
--- a/include/wx/glcanvas.h
+++ b/include/wx/glcanvas.h
@@ -20,14 +20,10 @@
// Most ports have a single implementation of wxGLCanvas, but wxGTK has two:
// legacy GLX-based one (also used by wxX11) and EGL-based one which is used
-// when enabled by wxUSE_GLCANVAS_EGL. Although it is not user-settable, define
-// wxUSE_GLCANVAS_GLX for consistency.
-#if defined(__WXX11__)
- #define wxUSE_GLCANVAS_GLX 1
-#elif defined(__WXGTK__)
- #define wxUSE_GLCANVAS_GLX (!wxUSE_GLCANVAS_EGL)
-#else
- #define wxUSE_GLCANVAS_GLX 0
+// if support for EGL is available. wxHAS_EGL is defined by the build system
+// but define wxHAS_GLX too for consistency, even if it's always available.
+#if defined(__WXX11__) || defined(__WXGTK__)
+ #define wxHAS_GLX 1
#endif
class WXDLLIMPEXP_FWD_GL wxGLCanvas;
@@ -146,16 +142,16 @@ public:
wxGLContextAttrs& PlatformDefaults();
void EndList(); // No more values can be chained
-#if wxUSE_GLCANVAS_GLX
+#ifdef wxHAS_GLX
// Currently only used for X11 context creation
bool x11Direct = false; // X11 direct render
bool renderTypeRGBA = false;
-#endif // wxUSE_GLCANVAS_GLX
+#endif // wxHAS_GLX
-#if wxUSE_GLCANVAS_EGL
+#ifdef wxHAS_EGL
// Used to select the kind of API used with EGL (OpenGL or OpenGL ES).
bool useES = false;
-#endif // wxUSE_GLCANVAS_EGL
+#endif // wxHAS_EGL
};
// ----------------------------------------------------------------------------
@@ -283,25 +279,27 @@ public:
// as a parameter
wxGLContextAttrs& GetGLCTXAttrs() { return m_GLCTXAttrs; }
-protected:
- // override this to implement SetColour() in GL_INDEX_MODE
- // (currently only implemented in wxX11)
- virtual int GetColourIndex(const wxColour& WXUNUSED(col)) { return -1; }
+ // Implementation only from now on.
// check if the given extension name is present in the space-separated list
// of extensions supported by the current implementation such as returned
// by glXQueryExtensionsString() or glGetString(GL_EXTENSIONS)
static bool IsExtensionInList(const char *list, const char *extension);
- // For the case of "int* attribList" at ctor is != 0
- wxGLContextAttrs m_GLCTXAttrs;
-
// Extract pixel format and context attributes.
// Return false if an unknown attribute is found.
static bool ParseAttribList(const int* attribList,
wxGLAttributes& dispAttrs,
wxGLContextAttrs* ctxAttrs = nullptr);
+protected:
+ // override this to implement SetColour() in GL_INDEX_MODE
+ // (currently only implemented in wxX11)
+ virtual int GetColourIndex(const wxColour& WXUNUSED(col)) { return -1; }
+
+ // For the case of "int* attribList" at ctor is != 0
+ wxGLContextAttrs m_GLCTXAttrs;
+
#if wxUSE_PALETTE
// create default palette if we're not using RGBA mode
// (not supported in most ports)
@@ -312,8 +310,9 @@ protected:
};
// ----------------------------------------------------------------------------
-// wxGLApp: a special wxApp subclass for OpenGL applications which must be used
-// to select a visual compatible with the given attributes
+// wxGLApp: Deprecated wxApp subclass for OpenGL applications, don't bother
+// using it any longer, just use wxGLCanvas::IsDisplaySupported() from
+// a normal wxApp-derived application class if necessary.
// ----------------------------------------------------------------------------
class WXDLLIMPEXP_GL wxGLAppBase : public wxApp
diff --git a/include/wx/gtk/app.h b/include/wx/gtk/app.h
index 389b6dc84f..d35ce9497c 100644
--- a/include/wx/gtk/app.h
+++ b/include/wx/gtk/app.h
@@ -46,11 +46,13 @@ public:
// GTK-specific methods
// -------------------
+#ifndef __WXGTK3__
// this can be overridden to return a specific visual to be used for GTK+
// instead of the default one (it's used by wxGLApp)
//
// must return XVisualInfo pointer (it is not freed by caller)
virtual void *GetXVisualInfo() { return nullptr; }
+#endif // GTK < 3
// Check if we're using a global menu. Currently this is only true when
// running under Ubuntu Unity and global menu is not disabled.
diff --git a/include/wx/gtk/glcanvas.h b/include/wx/gtk/glcanvas.h
index 32dde022cf..977b719859 100644
--- a/include/wx/gtk/glcanvas.h
+++ b/include/wx/gtk/glcanvas.h
@@ -10,23 +10,14 @@
#ifndef _WX_GLCANVAS_H_
#define _WX_GLCANVAS_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
+#include "wx/unix/glcanvas.h"
//---------------------------------------------------------------------------
// wxGLCanvas
//---------------------------------------------------------------------------
-class WXDLLIMPEXP_GL wxGLCanvas : public wxGLCanvasImpl
+class WXDLLIMPEXP_GL wxGLCanvas : public wxGLCanvasUnix
{
- typedef wxGLCanvasImpl BaseType;
public:
wxGLCanvas() = default;
@@ -69,7 +60,7 @@ public:
virtual bool SetBackgroundStyle(wxBackgroundStyle style) override;
- // implement wxGLCanvasX11 methods
+ // implement wxGLCanvasUnix methods
// --------------------------------
virtual unsigned long GetXWindow() const override;
diff --git a/include/wx/gtk/setup.h b/include/wx/gtk/setup.h
index a0a7d77c17..680e008815 100644
--- a/include/wx/gtk/setup.h
+++ b/include/wx/gtk/setup.h
@@ -1321,14 +1321,6 @@
// 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/msw/setup.h b/include/wx/msw/setup.h
index a1c003d000..1486b959f1 100644
--- a/include/wx/msw/setup.h
+++ b/include/wx/msw/setup.h
@@ -1321,14 +1321,6 @@
// 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/osx/setup.h b/include/wx/osx/setup.h
index aaee52b256..5bf95a043b 100644
--- a/include/wx/osx/setup.h
+++ b/include/wx/osx/setup.h
@@ -1328,14 +1328,6 @@
// 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/private/make_unique.h b/include/wx/private/make_unique.h
new file mode 100644
index 0000000000..d21ef005e5
--- /dev/null
+++ b/include/wx/private/make_unique.h
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/private/make_unique.h
+// Purpose: Provide implementation of std::make_unique for C++11
+// Author: Vadim Zeitlin
+// Created: 2025-12-10
+// Copyright: (c) 2025 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_PRIVATE_MAKE_UNIQUE_H_
+#define _WX_PRIVATE_MAKE_UNIQUE_H_
+
+#include
+
+#if !defined(_MSC_VER) && __cplusplus < 201402L
+ #include // for std::forward()
+
+ namespace std
+ {
+ template
+ std::unique_ptr make_unique(Args&&... args)
+ {
+ return std::unique_ptr(new T(std::forward(args)...));
+ }
+ }
+#endif
+
+#endif // _WX_PRIVATE_MAKE_UNIQUE_H_
diff --git a/include/wx/setup_inc.h b/include/wx/setup_inc.h
index cb4350ecfc..86499e826c 100644
--- a/include/wx/setup_inc.h
+++ b/include/wx/setup_inc.h
@@ -1317,14 +1317,6 @@
// 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/setup.h b/include/wx/univ/setup.h
index 998b4b0c70..e2a0d6e557 100644
--- a/include/wx/univ/setup.h
+++ b/include/wx/univ/setup.h
@@ -1321,14 +1321,6 @@
// 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/unix/glx11.h b/include/wx/unix/glcanvas.h
similarity index 56%
rename from include/wx/unix/glx11.h
rename to include/wx/unix/glcanvas.h
index cad490a878..437e6d2ccf 100644
--- a/include/wx/unix/glx11.h
+++ b/include/wx/unix/glcanvas.h
@@ -1,22 +1,27 @@
///////////////////////////////////////////////////////////////////////////////
-// Name: wx/unix/glx11.h
-// Purpose: class common for all X11-based wxGLCanvas implementations
+// Name: wx/unix/glcanvas.h
+// Purpose: class common for wxGLCanvas implementations in wxGTK and wxX11
// Author: Vadim Zeitlin
// Created: 2007-04-15
// Copyright: (c) 2007 Vadim Zeitlin
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
-#ifndef _WX_UNIX_GLX11_H_
-#define _WX_UNIX_GLX11_H_
+#ifndef _WX_UNIX_GLCANVAS_H_
+#define _WX_UNIX_GLCANVAS_H_
+
+#include
#include
-typedef struct __GLXcontextRec* GLXContext;
+// Forward declare struct from GL/glx.h
typedef struct __GLXFBConfigRec* GLXFBConfig;
+class wxGLContextImpl;
+class wxGLCanvasUnixImpl;
+
// ----------------------------------------------------------------------------
-// wxGLContext
+// wxGLContext: used as is in all ports
// ----------------------------------------------------------------------------
class WXDLLIMPEXP_GL wxGLContext : public wxGLContextBase
@@ -29,41 +34,42 @@ public:
virtual bool SetCurrent(const wxGLCanvas& win) const override;
+ // Implementation only.
+ wxGLContextImpl* GetImpl() const { return m_impl.get(); }
+
private:
- GLXContext m_glContext;
+ std::unique_ptr m_impl;
wxDECLARE_CLASS(wxGLContext);
};
// ----------------------------------------------------------------------------
-// wxGLCanvasX11
+// wxGLCanvasUnix: base class for port-specific wxGLCanvas
// ----------------------------------------------------------------------------
-class WXDLLIMPEXP_GL wxGLCanvasX11 : public wxGLCanvasBase
+class WXDLLIMPEXP_GL wxGLCanvasUnix : public wxGLCanvasBase
{
public:
- // initialization and dtor
- // -----------------------
-
- // default ctor doesn't do anything, InitVisual() must be called
- wxGLCanvasX11();
-
- // initializes GLXFBConfig and XVisualInfo corresponding to the given attributes
- bool InitVisual(const wxGLAttributes& dispAttrs);
-
- // frees XVisualInfo info
- virtual ~wxGLCanvasX11();
-
-
- // implement wxGLCanvasBase methods
- // --------------------------------
+ virtual ~wxGLCanvasUnix();
virtual bool SwapBuffers() override;
+ virtual bool IsShownOnScreen() const override;
- // X11-specific methods
+ // EGL-specific methods
// --------------------
+ // return true when using EGL, filling major and minor with EGL version
+ static bool GetEGLVersion(int* major, int* minor);
+
+
+ // GLX-specific methods
+ // --------------------
+
+ // if both GLX and EGL are available, prefer using GLX instead of EGL used
+ // by default
+ static void PreferGLX();
+
// return GLX version: 13 means 1.3 &c
static int GetGLXVersion();
@@ -74,33 +80,21 @@ public:
virtual unsigned long GetXWindow() const = 0;
- // GLX-specific methods
- // --------------------
+ // Implementation only.
+ wxGLCanvasUnixImpl* GetImpl() const { return m_impl.get(); }
- // override some wxWindow methods
- // ------------------------------
+ void* GetXVisualInfo() const;
- // return true only if the window is realized: OpenGL context can't be
- // created until we are
- virtual bool IsShownOnScreen() const override;
+protected:
+ wxGLCanvasUnix();
+ bool InitVisual(const wxGLAttributes& dispAttrs);
- // implementation only from now on
- // -------------------------------
-
- // get the GLXFBConfig/XVisualInfo we use
- GLXFBConfig *GetGLXFBConfig() const { return m_fbc; }
- void* GetXVisualInfo() const { return m_vi; }
-
- // initialize the global default GL visual, return false if matching visual
- // not found
- static bool InitDefaultVisualInfo(const int *attribList);
+ // This is only called by wxGTK but defined in any case.
+ void CallOnRealized();
private:
- GLXFBConfig *m_fbc;
- void* m_vi;
-
- bool m_swapIntervalSet = false;
+ std::unique_ptr m_impl;
};
// ----------------------------------------------------------------------------
@@ -113,12 +107,11 @@ private:
class WXDLLIMPEXP_GL wxGLApp : public wxGLAppBase
{
public:
+ wxGLApp() = default;
+
virtual bool InitGLVisual(const int *attribList) override;
- // 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() override;
+ virtual void* GetXVisualInfo();
// and override this wxApp method to clean up
virtual int OnExit() override;
@@ -127,5 +120,4 @@ private:
wxDECLARE_DYNAMIC_CLASS(wxGLApp);
};
-#endif // _WX_UNIX_GLX11_H_
-
+#endif // _WX_UNIX_GLCANVAS_H_
diff --git a/include/wx/unix/glegl.h b/include/wx/unix/glegl.h
deleted file mode 100644
index 5155a84151..0000000000
--- a/include/wx/unix/glegl.h
+++ /dev/null
@@ -1,206 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// 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 = nullptr,
- const wxGLContextAttrs *ctxAttrs = nullptr);
- virtual ~wxGLContext();
-
- virtual bool SetCurrent(const wxGLCanvas& win) const override;
-
-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() = default;
-
- // initializes EGLConfig corresponding to the given attributes
- bool InitVisual(const wxGLAttributes& dispAttrs);
-
- // creates EGLSurface
- bool CreateSurface();
-
- virtual ~wxGLCanvasEGL();
-
- // Wayland-specific callbacks
- // --------------------------
-
- void CreateWaylandSubsurface();
- void DestroyWaylandSubsurface();
-
- // implement wxGLCanvasBase methods
- // --------------------------------
-
- virtual bool SwapBuffers() override;
-
-
- // 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 override;
-
-
- // 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 nullptr if EGLConfig couldn't be initialized, otherwise caller
- // is responsible for freeing the pointer
- static EGLConfig InitConfig(const wxGLAttributes& dispAttrs);
-
- // Only called when using Wayland to indicate that we should be redrawn.
- void OnWLFrameCallback();
-
- wl_compositor *m_wlCompositor = nullptr;
- wl_subcompositor *m_wlSubcompositor = nullptr;
- wl_callback *m_wlFrameCallbackHandler = nullptr;
- wl_egl_window *m_wlEGLWindow = nullptr;
-
-private:
- // Set correct m_wlSubsurface position.
- //
- // This is defined only when using Wayland.
- void UpdateSubsurfacePosition();
-
- // Call eglCreatePlatformWindowSurface() when using EGL 1.5 or later,
- // otherwise try eglCreatePlatformWindowSurfaceEXT() if it's available and
- // fall back on eglCreateWindowSurface() otherwise.
- //
- // This function uses m_display and m_config which must be initialized
- // before using it and should be passed either m_xwindow or m_wlEGLWindow
- // depending on whether we are using X11 or Wayland.
- EGLSurface CallCreatePlatformWindowSurface(void *window) const;
-
-
- EGLConfig m_config = nullptr;
- EGLDisplay m_display = nullptr;
- EGLSurface m_surface = nullptr;
-
- unsigned long m_xwindow = 0;
- wl_surface *m_wlSurface = nullptr;
- wl_region *m_wlRegion = nullptr;
- wl_subsurface *m_wlSubsurface = nullptr;
-
- bool m_readyToDraw = false;
- bool m_swapIntervalSet = false;
-
- // the global/default versions of the above
- static EGLConfig ms_glEGLConfig;
-
- // Called from GTK callbacks and needs access to private members.
- friend void wxEGLUpdateGeometry(GtkWidget* widget, wxGLCanvasEGL* win);
-};
-
-// ----------------------------------------------------------------------------
-// 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) override
- {
- 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() override
- {
- return wxGLCanvasEGL::GetDefaultConfig();
- }
-
- // and override this wxApp method to clean up
- virtual int OnExit() override
- {
- wxGLCanvasEGL::FreeDefaultConfig();
-
- return wxGLAppBase::OnExit();
- }
-
-private:
- wxDECLARE_DYNAMIC_CLASS(wxGLApp);
-};
-
-#endif // _WX_UNIX_GLEGL_H_
diff --git a/include/wx/unix/private/glcanvas.h b/include/wx/unix/private/glcanvas.h
new file mode 100644
index 0000000000..90cfc194d3
--- /dev/null
+++ b/include/wx/unix/private/glcanvas.h
@@ -0,0 +1,163 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/unix/private/glcontext.h
+// Purpose: Base class for Unix-specific wxGLContext implementation
+// Author: Vadim Zeitlin
+// Created: 2025-12-07
+// Copyright: (c) 2025 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_UNIX_PRIVATE_GLCANVAS_H_
+#define _WX_UNIX_PRIVATE_GLCANVAS_H_
+
+// ----------------------------------------------------------------------------
+// wxGLContextImpl is used by wxGLContext to implement its functionality
+// ----------------------------------------------------------------------------
+
+class wxGLContextImpl
+{
+public:
+ virtual ~wxGLContextImpl() = default;
+
+ virtual bool SetCurrent(const wxGLCanvas& win) const = 0;
+
+ bool IsOK() const { return m_isOk; }
+
+protected:
+ wxGLContextImpl() = default;
+
+ // This is similar to wxGLContextBase::m_isOk and allows to keep the
+ // code from before the refactoring which introduced this class unchanged.
+ bool m_isOk = false;
+
+ wxDECLARE_NO_COPY_CLASS(wxGLContextImpl);
+};
+
+// ----------------------------------------------------------------------------
+// wxGLCanvasUnixImpl: note that this is not a wxWindow-derived class
+// ----------------------------------------------------------------------------
+
+class wxGLCanvasUnixImpl
+{
+public:
+ virtual ~wxGLCanvasUnixImpl() = default;
+
+ virtual bool InitVisual(const wxGLAttributes& dispAttrs) = 0;
+
+ virtual bool SwapBuffers() = 0;
+
+ virtual void OnRealized() = 0;
+
+ virtual bool HasWindow() const = 0;
+
+ virtual void* GetXVisualInfo() const = 0;
+
+protected:
+ explicit wxGLCanvasUnixImpl(wxGLCanvasUnix* canvas)
+ : m_canvas(canvas)
+ {
+ }
+
+ wxGLCanvasUnix* const m_canvas;
+
+ wxDECLARE_NO_COPY_CLASS(wxGLCanvasUnixImpl);
+};
+
+// ----------------------------------------------------------------------------
+// wxGLBackend: used for creating implementation objects and implementing other
+// non-member functions.
+// ----------------------------------------------------------------------------
+
+class wxGLBackend
+{
+public:
+#ifdef wxHAS_EGL
+ // This can be called only before calling Get() for the first time.
+ static void PreferGLX();
+#endif // wxHAS_EGL
+
+ // Get the (sole) instance of this class.
+ static wxGLBackend& Get()
+ {
+ if ( !ms_instance )
+ ms_instance = Init();
+
+ return *ms_instance;
+ }
+
+ wxGLBackend(const wxGLBackend&) = delete;
+ wxGLBackend& operator=(const wxGLBackend&) = delete;
+
+ virtual ~wxGLBackend() = default;
+
+ // Factory functions for creating the implementation objects.
+
+ virtual std::unique_ptr
+ CreateContextImpl(wxGLCanvas* win,
+ const wxGLContext* other,
+ const wxGLContextAttrs* ctxAttrs) = 0;
+
+ virtual std::unique_ptr
+ CreateCanvasImpl(wxGLCanvasUnix* canvas) = 0;
+
+ // Static functions of wxGLContext and wxGLCanvas.
+ virtual void ClearCurrentContext() = 0;
+
+ virtual bool IsExtensionSupported(const char* extension) = 0;
+
+ virtual bool IsDisplaySupported(const wxGLAttributes& dispAttrs) = 0;
+
+ virtual bool GetEGLVersion(int* major, int* minor) = 0;
+ virtual int GetGLXVersion() = 0;
+
+ virtual bool IsGLXMultiSampleAvailable() = 0;
+
+ // wxGLApp functions implementation.
+ virtual bool InitDefaultVisualInfo(const int* attribList) = 0;
+ virtual void* GetDefaultVisualInfo() = 0;
+ virtual void FreeDefaultVisualInfo() = 0;
+
+ // wxGLContextAttrs functions implementation.
+ virtual wxGLContextAttrs& CoreProfile(wxGLContextAttrs& attrs) = 0;
+ virtual wxGLContextAttrs& MajorVersion(wxGLContextAttrs& attrs, int val) = 0;
+ virtual wxGLContextAttrs& MinorVersion(wxGLContextAttrs& attrs, int val) = 0;
+ virtual wxGLContextAttrs& CompatibilityProfile(wxGLContextAttrs& attrs) = 0;
+ virtual wxGLContextAttrs& ForwardCompatible(wxGLContextAttrs& attrs) = 0;
+ virtual wxGLContextAttrs& ES2(wxGLContextAttrs& attrs) = 0;
+ virtual wxGLContextAttrs& DebugCtx(wxGLContextAttrs& attrs) = 0;
+ virtual wxGLContextAttrs& Robust(wxGLContextAttrs& attrs) = 0;
+ virtual wxGLContextAttrs& NoResetNotify(wxGLContextAttrs& attrs) = 0;
+ virtual wxGLContextAttrs& LoseOnReset(wxGLContextAttrs& attrs) = 0;
+ virtual wxGLContextAttrs& ResetIsolation(wxGLContextAttrs& attrs) = 0;
+ virtual wxGLContextAttrs& ReleaseFlush(wxGLContextAttrs& attrs, int val) = 0;
+ virtual wxGLContextAttrs& PlatformDefaults(wxGLContextAttrs& attrs) = 0;
+
+ // wxGLAttributes functions implementation.
+ virtual wxGLAttributes& RGBA(wxGLAttributes& attrs) = 0;
+ virtual wxGLAttributes& BufferSize(wxGLAttributes& attrs, int val) = 0;
+ virtual wxGLAttributes& Level(wxGLAttributes& attrs, int val) = 0;
+ virtual wxGLAttributes& DoubleBuffer(wxGLAttributes& attrs) = 0;
+ virtual wxGLAttributes& Stereo(wxGLAttributes& attrs) = 0;
+ virtual wxGLAttributes& AuxBuffers(wxGLAttributes& attrs, int val) = 0;
+ virtual wxGLAttributes& MinRGBA(wxGLAttributes& attrs, int mRed, int mGreen, int mBlue, int mAlpha) = 0;
+ virtual wxGLAttributes& Depth(wxGLAttributes& attrs, int val) = 0;
+ virtual wxGLAttributes& Stencil(wxGLAttributes& attrs, int val) = 0;
+ virtual wxGLAttributes& MinAcumRGBA(wxGLAttributes& attrs, int mRed, int mGreen, int mBlue, int mAlpha) = 0;
+ virtual wxGLAttributes& PlatformDefaults(wxGLAttributes& attrs) = 0;
+ virtual wxGLAttributes& SampleBuffers(wxGLAttributes& attrs, int val) = 0;
+ virtual wxGLAttributes& Samplers(wxGLAttributes& attrs, int val) = 0;
+ virtual wxGLAttributes& FrameBuffersRGB(wxGLAttributes& attrs) = 0;
+
+ // Both kinds of attributes are terminated in the same way.
+ virtual void EndList(wxGLAttribsBase& attrs) = 0;
+
+protected:
+ wxGLBackend() = default;
+
+private:
+ static wxGLBackend* Init();
+
+ static wxGLBackend* ms_instance;
+};
+
+#endif // _WX_UNIX_PRIVATE_GLCANVAS_H_
diff --git a/include/wx/unix/private/glegl.h b/include/wx/unix/private/glegl.h
new file mode 100644
index 0000000000..705c518224
--- /dev/null
+++ b/include/wx/unix/private/glegl.h
@@ -0,0 +1,189 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/unix/private/glegl.h
+// Purpose: wxGLContext EGL-based implementation
+// Author: Vadim Zeitlin
+// Created: 2025-12-07
+// Copyright: (c) 2025 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_UNIX_PRIVATE_GLEGL_H_
+#define _WX_UNIX_PRIVATE_GLEGL_H_
+
+#include "wx/unix/private/glcanvas.h"
+
+#include
+#include
+
+struct wl_compositor;
+struct wl_subcompositor;
+struct wl_callback;
+struct wl_egl_window;
+struct wl_surface;
+struct wl_region;
+struct wl_subsurface;
+
+// ----------------------------------------------------------------------------
+// wxGLContextEGL
+// ----------------------------------------------------------------------------
+
+class wxGLContextEGL : public wxGLContextImpl
+{
+public:
+ wxGLContextEGL(wxGLCanvas *win,
+ const wxGLContext *other = nullptr,
+ const wxGLContextAttrs *ctxAttrs = nullptr);
+ virtual ~wxGLContextEGL();
+
+ virtual bool SetCurrent(const wxGLCanvas& win) const override;
+
+private:
+ EGLContext m_glContext;
+};
+
+// ----------------------------------------------------------------------------
+// wxGLCanvasEGL
+// ----------------------------------------------------------------------------
+
+class wxGLCanvasEGL : public wxGLCanvasUnixImpl
+{
+public:
+ explicit wxGLCanvasEGL(wxGLCanvasUnix* canvas)
+ : wxGLCanvasUnixImpl(canvas)
+ {
+ }
+
+ virtual ~wxGLCanvasEGL() override;
+
+ virtual bool InitVisual(const wxGLAttributes& dispAttrs) override;
+
+ virtual bool SwapBuffers() override;
+
+ virtual void OnRealized() override;
+
+ virtual bool HasWindow() const override;
+
+ virtual void* GetXVisualInfo() const override { return nullptr; }
+
+ // implementation only from now on
+ // -------------------------------
+
+ void CreateWaylandSubsurface();
+ void DestroyWaylandSubsurface();
+
+ EGLConfig GetEGLConfig() const { return m_config; }
+ EGLDisplay GetEGLDisplay() const { return m_display; }
+ EGLSurface GetEGLSurface() const { return m_surface; }
+
+ static EGLDisplay GetDisplay();
+
+ // initializes EGLConfig
+ //
+ // returns nullptr if EGLConfig couldn't be initialized, otherwise caller
+ // is responsible for freeing the pointer
+ static EGLConfig InitConfig(const wxGLAttributes& dispAttrs);
+
+ // Only called when using Wayland to indicate that we should be redrawn.
+ void OnWLFrameCallback();
+
+ wl_compositor *m_wlCompositor = nullptr;
+ wl_subcompositor *m_wlSubcompositor = nullptr;
+ wl_callback *m_wlFrameCallbackHandler = nullptr;
+ wl_egl_window *m_wlEGLWindow = nullptr;
+
+private:
+ // Set correct m_wlSubsurface position.
+ //
+ // This is defined only when using Wayland.
+ void UpdateSubsurfacePosition();
+
+ // Call eglCreatePlatformWindowSurface() when using EGL 1.5 or later,
+ // otherwise try eglCreatePlatformWindowSurfaceEXT() if it's available and
+ // fall back on eglCreateWindowSurface() otherwise.
+ //
+ // This function uses m_display and m_config which must be initialized
+ // before using it and should be passed either m_xwindow or m_wlEGLWindow
+ // depending on whether we are using X11 or Wayland.
+ EGLSurface CallCreatePlatformWindowSurface(void *window) const;
+
+
+ EGLConfig m_config = nullptr;
+ EGLDisplay m_display = nullptr;
+ EGLSurface m_surface = nullptr;
+
+ unsigned long m_xwindow = 0;
+ wl_surface *m_wlSurface = nullptr;
+ wl_region *m_wlRegion = nullptr;
+ wl_subsurface *m_wlSubsurface = nullptr;
+
+ bool m_readyToDraw = false;
+ bool m_swapIntervalSet = false;
+
+ // Called from GTK callbacks and needs access to private members.
+ friend void wxEGLUpdateGeometry(GtkWidget* widget, wxGLCanvasEGL* win);
+};
+
+// ----------------------------------------------------------------------------
+// wxGLBackendEGL
+// ----------------------------------------------------------------------------
+
+class wxGLBackendEGL : public wxGLBackend
+{
+public:
+ static wxGLBackend& Get();
+
+ wxGLBackendEGL() = default;
+
+ std::unique_ptr
+ CreateContextImpl(wxGLCanvas* win,
+ const wxGLContext* other,
+ const wxGLContextAttrs* ctxAttrs) override;
+
+ std::unique_ptr
+ CreateCanvasImpl(wxGLCanvasUnix* canvas) override;
+
+ void ClearCurrentContext() override;
+
+ bool IsExtensionSupported(const char* extension) override;
+ bool IsDisplaySupported(const wxGLAttributes& dispAttrs) override;
+ bool GetEGLVersion(int* major, int* minor) override;
+ int GetGLXVersion() override;
+ bool IsGLXMultiSampleAvailable() override;
+
+ bool InitDefaultVisualInfo(const int* attribList) override;
+ void* GetDefaultVisualInfo() override;
+ void FreeDefaultVisualInfo() override;
+
+ wxGLContextAttrs& CoreProfile(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& MajorVersion(wxGLContextAttrs& attrs, int val) override;
+ wxGLContextAttrs& MinorVersion(wxGLContextAttrs& attrs, int val) override;
+ wxGLContextAttrs& CompatibilityProfile(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& ForwardCompatible(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& ES2(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& DebugCtx(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& Robust(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& NoResetNotify(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& LoseOnReset(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& ResetIsolation(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& ReleaseFlush(wxGLContextAttrs& attrs, int val) override;
+ wxGLContextAttrs& PlatformDefaults(wxGLContextAttrs& attrs) override;
+
+ wxGLAttributes& RGBA(wxGLAttributes& attrs) override;
+ wxGLAttributes& BufferSize(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& Level(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& DoubleBuffer(wxGLAttributes& attrs) override;
+ wxGLAttributes& Stereo(wxGLAttributes& attrs) override;
+ wxGLAttributes& AuxBuffers(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& MinRGBA(wxGLAttributes& attrs, int mRed, int mGreen, int mBlue, int mAlpha) override;
+ wxGLAttributes& Depth(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& Stencil(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& MinAcumRGBA(wxGLAttributes& attrs, int mRed, int mGreen, int mBlue, int mAlpha) override;
+ wxGLAttributes& PlatformDefaults(wxGLAttributes& attrs) override;
+ wxGLAttributes& SampleBuffers(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& Samplers(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& FrameBuffersRGB(wxGLAttributes& attrs) override;
+
+ void EndList(wxGLAttribsBase& attrs) override;
+};
+
+#endif // _WX_UNIX_PRIVATE_GLEGL_H_
diff --git a/include/wx/unix/private/glx11.h b/include/wx/unix/private/glx11.h
new file mode 100644
index 0000000000..4d15d898b0
--- /dev/null
+++ b/include/wx/unix/private/glx11.h
@@ -0,0 +1,132 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/unix/private/glx11.h
+// Purpose: wxGLContext GLX-based implementation for X11
+// Author: Vadim Zeitlin
+// Created: 2025-12-07
+// Copyright: (c) 2025 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_UNIX_PRIVATE_GLX11_H_
+#define _WX_UNIX_PRIVATE_GLX11_H_
+
+#include "wx/unix/private/glcanvas.h"
+
+#include
+
+// ----------------------------------------------------------------------------
+// wxGLContextX11
+// ----------------------------------------------------------------------------
+
+class wxGLContextX11 : public wxGLContextImpl
+{
+public:
+ wxGLContextX11(wxGLCanvas *win,
+ const wxGLContext *other = nullptr,
+ const wxGLContextAttrs *ctxAttrs = nullptr);
+ virtual ~wxGLContextX11();
+
+ virtual bool SetCurrent(const wxGLCanvas& win) const override;
+
+private:
+ GLXContext m_glContext;
+};
+
+// ----------------------------------------------------------------------------
+// wxGLCanvasX11
+// ----------------------------------------------------------------------------
+
+class wxGLCanvasX11 : public wxGLCanvasUnixImpl
+{
+public:
+ explicit wxGLCanvasX11(wxGLCanvasUnix* canvas);
+
+ virtual ~wxGLCanvasX11() override;
+
+ virtual bool InitVisual(const wxGLAttributes& dispAttrs) override;
+
+ virtual bool SwapBuffers() override;
+
+ virtual void OnRealized() override { /* nothing to do here for GLX */ }
+
+ virtual bool HasWindow() const override;
+
+ virtual void* GetXVisualInfo() const override { return m_vi; }
+
+ GLXFBConfig *GetGLXFBConfig() const { return m_fbc; }
+
+ // initialize the global default GL visual, return false if matching visual
+ // not found
+ static bool InitDefaultVisualInfo(const int *attribList);
+
+private:
+ GLXFBConfig *m_fbc;
+ XVisualInfo* m_vi;
+
+ bool m_swapIntervalSet = false;
+};
+
+// ----------------------------------------------------------------------------
+// wxGLBackendX11
+// ----------------------------------------------------------------------------
+
+class wxGLBackendX11 : public wxGLBackend
+{
+public:
+ static wxGLBackend& Get();
+
+ wxGLBackendX11() = default;
+
+ std::unique_ptr
+ CreateContextImpl(wxGLCanvas* win,
+ const wxGLContext* other,
+ const wxGLContextAttrs* ctxAttrs) override;
+
+ std::unique_ptr
+ CreateCanvasImpl(wxGLCanvasUnix* canvas) override;
+
+ void ClearCurrentContext() override;
+
+ bool IsExtensionSupported(const char* extension) override;
+ bool IsDisplaySupported(const wxGLAttributes& dispAttrs) override;
+ bool GetEGLVersion(int* major, int* minor) override;
+ int GetGLXVersion() override;
+ bool IsGLXMultiSampleAvailable() override;
+
+ bool InitDefaultVisualInfo(const int* attribList) override;
+ void* GetDefaultVisualInfo() override;
+ void FreeDefaultVisualInfo() override;
+
+ wxGLContextAttrs& CoreProfile(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& MajorVersion(wxGLContextAttrs& attrs, int val) override;
+ wxGLContextAttrs& MinorVersion(wxGLContextAttrs& attrs, int val) override;
+ wxGLContextAttrs& CompatibilityProfile(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& ForwardCompatible(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& ES2(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& DebugCtx(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& Robust(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& NoResetNotify(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& LoseOnReset(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& ResetIsolation(wxGLContextAttrs& attrs) override;
+ wxGLContextAttrs& ReleaseFlush(wxGLContextAttrs& attrs, int val) override;
+ wxGLContextAttrs& PlatformDefaults(wxGLContextAttrs& attrs) override;
+
+ wxGLAttributes& RGBA(wxGLAttributes& attrs) override;
+ wxGLAttributes& BufferSize(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& Level(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& DoubleBuffer(wxGLAttributes& attrs) override;
+ wxGLAttributes& Stereo(wxGLAttributes& attrs) override;
+ wxGLAttributes& AuxBuffers(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& MinRGBA(wxGLAttributes& attrs, int mRed, int mGreen, int mBlue, int mAlpha) override;
+ wxGLAttributes& Depth(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& Stencil(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& MinAcumRGBA(wxGLAttributes& attrs, int mRed, int mGreen, int mBlue, int mAlpha) override;
+ wxGLAttributes& PlatformDefaults(wxGLAttributes& attrs) override;
+ wxGLAttributes& SampleBuffers(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& Samplers(wxGLAttributes& attrs, int val) override;
+ wxGLAttributes& FrameBuffersRGB(wxGLAttributes& attrs) override;
+
+ void EndList(wxGLAttribsBase& attrs) override;
+};
+
+#endif // _WX_UNIX_PRIVATE_GLX11_H_
diff --git a/include/wx/x11/glcanvas.h b/include/wx/x11/glcanvas.h
index 200261970e..8a58b4b181 100644
--- a/include/wx/x11/glcanvas.h
+++ b/include/wx/x11/glcanvas.h
@@ -11,9 +11,9 @@
#ifndef _WX_GLCANVAS_H_
#define _WX_GLCANVAS_H_
-#include "wx/unix/glx11.h"
+#include "wx/unix/glcanvas.h"
-class WXDLLIMPEXP_GL wxGLCanvas : public wxGLCanvasX11
+class WXDLLIMPEXP_GL wxGLCanvas : public wxGLCanvasUnix
{
public:
wxGLCanvas() = default;
@@ -55,7 +55,7 @@ public:
const int *attribList = nullptr,
const wxPalette& palette = wxNullPalette);
- // implement wxGLCanvasX11 methods
+ // implement wxGLCanvasUnix methods
// --------------------------------
virtual unsigned long GetXWindow() const;
diff --git a/interface/wx/glcanvas.h b/interface/wx/glcanvas.h
index dcc0781059..d69c712ae7 100644
--- a/interface/wx/glcanvas.h
+++ b/interface/wx/glcanvas.h
@@ -899,16 +899,37 @@ public:
/**
- Re-creates EGLSurface. To be used after a reparent or other
- changes that may invalidate the EGL drawing surface.
+ Return the version of EGL being used or @false if not using EGL.
- Only available when wxUSE_GLCANVAS_EGL is enabled.
+ This function is only available when `wxHAS_GLX` preprocessor symbol is
+ defined, i.e. in the builds where either GLX or EGL can be used. Note
+ that it is still available when `wxHAS_EGL` is _not_ defined, and
+ simply always returns @false in this case.
- @return @true if surface is successfully recreated
+ @param major
+ Pointer to an integer to receive the major version number. May be
+ @NULL.
+ @param minor
+ Pointer to an integer to receive the minor version number. May be
+ @NULL.
+ @return
+ @true if EGL is being used and version numbers were returned,
+ @false otherwise, e.g. if GLX is being used instead.
- @since 3.2.3
- */
- bool CreateSurface();
+ @since 3.3.2
+ */
+ static bool GetEGLVersion(int* major, int* minor);
+
+ /**
+ Return the version of GLX being used or 0 if not using GLX.
+
+ The returned value combines major and minor version numbers in a
+ single integer, e.g. version 1.3 will be returned as 13.
+
+ This function is only available when `wxHAS_GLX` preprocessor symbol is
+ defined (which will be the case for wxGTK and wxX11 under Unix systems).
+ */
+ static int GetGLXVersion();
/**
Determines if a canvas having the specified attributes is available.
@@ -945,6 +966,28 @@ public:
*/
static bool IsExtensionSupported(const char *extension);
+ /**
+ Prefer using GLX over other OpenGL implementations on Unix-like systems
+ where multiple implementations are available (such as GLX and EGL).
+
+ This function is only available when `wxHAS_GLX` preprocessor symbol is
+ defined (which will be the case for wxGTK and wxX11 under Unix systems).
+
+ It must be called before using any OpenGL functionality, which includes
+ not only creating wxGLCanvas but also checking for extension support or
+ creating attributes objects, doing it afterwards will trigger an assert
+ failure and have no other effect.
+
+ Note that when using wxGTK with Wayland, calling this function will
+ have no effect anyhow as only EGL is supported in this case.
+
+ Finally please note that the same effect can be achieved by setting the
+ environment variable `wx_opengl_egl=0` before starting the application.
+
+ @since 3.3.2
+ */
+ static void PreferGLX();
+
/**
Sets the current colour for this window (using @c glcolor3f()), using
the wxWidgets colour database to find a named colour.
diff --git a/samples/opengl/cube/cube.cpp b/samples/opengl/cube/cube.cpp
index f2b628ac9d..dbaaade98e 100644
--- a/samples/opengl/cube/cube.cpp
+++ b/samples/opengl/cube/cube.cpp
@@ -450,6 +450,7 @@ wxString glGetwxString(GLenum name)
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(wxID_NEW, MyFrame::OnNewWindow)
EVT_MENU(NEW_STEREO_WINDOW, MyFrame::OnNewStereoWindow)
+ EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
EVT_MENU(wxID_CLOSE, MyFrame::OnClose)
wxEND_EVENT_TABLE()
@@ -465,6 +466,8 @@ MyFrame::MyFrame( bool stereoWindow )
menu->Append(wxID_NEW);
menu->Append(NEW_STEREO_WINDOW, "New Stereo Window");
menu->AppendSeparator();
+ menu->Append(wxID_ABOUT, "&About...\tF1");
+ menu->AppendSeparator();
menu->Append(wxID_CLOSE);
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menu, "&Cube");
@@ -492,6 +495,48 @@ MyFrame::MyFrame( bool stereoWindow )
}
}
+void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
+{
+ wxString info = "This is the wxWidgets OpenGL Cube sample.\n\n";
+
+#ifdef wxHAS_GLX
+ const int glxVersion = wxGLCanvasUnix::GetGLXVersion();
+ if ( glxVersion == 0 )
+ {
+ int eglMajor = 0, eglMinor = 0;
+ if ( wxGLCanvasUnix::GetEGLVersion(&eglMajor, &eglMinor) )
+ {
+ info += wxString::Format("Using EGL %d.%d.\n\n",
+ eglMajor, eglMinor);
+ }
+ else
+ {
+ info += "Using unknown OpenGL binding API.\n\n";
+ }
+ }
+ else
+ {
+ info += wxString::Format("Using GLX %d.%d.\n\n",
+ glxVersion / 10, glxVersion % 10);
+ }
+#endif // wxHAS_GLX
+
+ auto const getString = [](GLenum name) -> wxString
+ {
+ const GLubyte* const str = glGetString(name);
+ return wxString::FromUTF8(reinterpret_cast(str));
+ };
+
+ info += wxString::Format("OpenGL version: %s\n", getString(GL_VERSION));
+ info += wxString::Format("OpenGL vendor: %s\n", getString(GL_VENDOR));
+ info += wxString::Format("OpenGL renderer: %s", getString(GL_RENDERER));
+
+ wxMessageBox(info,
+ "About wxWidgets OpenGL cube sample",
+ wxOK | wxICON_INFORMATION,
+ this);
+}
+
void MyFrame::OnClose(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
diff --git a/samples/opengl/cube/cube.h b/samples/opengl/cube/cube.h
index 1ea4f0506d..5669992588 100644
--- a/samples/opengl/cube/cube.h
+++ b/samples/opengl/cube/cube.h
@@ -54,6 +54,7 @@ public:
MyFrame(bool stereoWindow = false);
private:
+ void OnAbout(wxCommandEvent& event);
void OnClose(wxCommandEvent& event);
void OnNewWindow(wxCommandEvent& event);
void OnNewStereoWindow(wxCommandEvent& event);
diff --git a/setup.h.in b/setup.h.in
index f8635104d3..c34b935bf1 100644
--- a/setup.h.in
+++ b/setup.h.in
@@ -506,8 +506,6 @@
#define wxUSE_GLCANVAS 0
-#define wxUSE_GLCANVAS_EGL 0
-
#define wxUSE_RICHTEXT 0
@@ -1138,6 +1136,9 @@
/* Define if locale_t is available */
#undef HAVE_LOCALE_T
+/* Define if you have EGL support */
+#undef wxHAS_EGL
+
/* Define if you have inotify_xxx() functions. */
#undef wxHAS_INOTIFY
diff --git a/setup.h_vms b/setup.h_vms
index e8bed9a022..ca1acdd574 100644
--- a/setup.h_vms
+++ b/setup.h_vms
@@ -553,8 +553,6 @@ typedef pid_t GPid;
#define wxUSE_GLCANVAS 1
-#define wxUSE_GLCANVAS_EGL 0
-
#define wxUSE_RICHTEXT 1
#define wxUSE_CLIPBOARD 1
diff --git a/src/gtk/glcanvas.cpp b/src/gtk/glcanvas.cpp
index 1ea762295b..fac1bb9393 100644
--- a/src/gtk/glcanvas.cpp
+++ b/src/gtk/glcanvas.cpp
@@ -42,7 +42,6 @@ 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,7 +69,6 @@ parent_set_hook(GSignalInvocationHint*, guint, const GValue* param_values, void*
return true;
}
}
-#endif
//---------------------------------------------------------------------------
// wxGlCanvas
@@ -111,12 +109,12 @@ static bool IsAvailable()
#ifdef GDK_WINDOWING_WAYLAND
if (wxGTKImpl::IsWayland(display))
{
-#if wxUSE_GLCANVAS_EGL
+#ifdef wxHAS_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 // wxHAS_EGL/!wxHAS_EGL
}
#endif // GDK_WINDOWING_WAYLAND
@@ -183,10 +181,11 @@ 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, nullptr);
-#endif
+ if ( GetGLXVersion() )
+ {
+ unsigned sig_id = g_signal_lookup("parent-set", GTK_TYPE_WIDGET);
+ g_signal_add_emission_hook(sig_id, 0, parent_set_hook, this, nullptr);
+ }
wxWindow::Create( parent, id, pos, size, style, name );
#ifdef __WXGTK3__
@@ -217,11 +216,10 @@ unsigned long wxGLCanvas::GetXWindow() const
void wxGLCanvas::GTKHandleRealized()
{
- BaseType::GTKHandleRealized();
+ wxGLCanvasUnix::GTKHandleRealized();
+
+ CallOnRealized();
-#if wxUSE_GLCANVAS_EGL
- CreateSurface();
-#endif
SendSizeEvent();
}
diff --git a/src/unix/glcanvas.cpp b/src/unix/glcanvas.cpp
new file mode 100644
index 0000000000..4afc7046b2
--- /dev/null
+++ b/src/unix/glcanvas.cpp
@@ -0,0 +1,362 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: src/unix/glcanvas.cpp
+// Purpose: wxGLCanvas implementation common to wxGTK and wxX11
+// Author: Vadim Zeitlin
+// Created: 2025-12-07
+// Copyright: (c) 2025 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#include "wx/sysopt.h"
+
+#include "wx/glcanvas.h"
+
+#include "wx/unix/private/glcanvas.h"
+#include "wx/unix/private/glx11.h"
+#ifdef wxHAS_EGL
+ #include "wx/unix/private/glegl.h"
+
+ #ifdef __WXGTK3__
+ #include "wx/gtk/private/wrapgdk.h"
+ #include "wx/gtk/private/backend.h"
+ #endif // __WXGTK3__
+#endif // wxHAS_EGL
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxGLContextAttrs: OpenGL rendering context attributes
+// ----------------------------------------------------------------------------
+
+wxGLContextAttrs& wxGLContextAttrs::CoreProfile()
+{
+ return wxGLBackend::Get().CoreProfile(*this);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::MajorVersion(int val)
+{
+ return wxGLBackend::Get().MajorVersion(*this, val);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::MinorVersion(int val)
+{
+ return wxGLBackend::Get().MinorVersion(*this, val);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::CompatibilityProfile()
+{
+ return wxGLBackend::Get().CompatibilityProfile(*this);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::ForwardCompatible()
+{
+ return wxGLBackend::Get().ForwardCompatible(*this);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::ES2()
+{
+ return wxGLBackend::Get().ES2(*this);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::DebugCtx()
+{
+ return wxGLBackend::Get().DebugCtx(*this);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::Robust()
+{
+ return wxGLBackend::Get().Robust(*this);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::NoResetNotify()
+{
+ return wxGLBackend::Get().NoResetNotify(*this);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::LoseOnReset()
+{
+ return wxGLBackend::Get().LoseOnReset(*this);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::ResetIsolation()
+{
+ return wxGLBackend::Get().ResetIsolation(*this);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::ReleaseFlush(int val)
+{
+ return wxGLBackend::Get().ReleaseFlush(*this, val);
+}
+
+wxGLContextAttrs& wxGLContextAttrs::PlatformDefaults()
+{
+ return wxGLBackend::Get().PlatformDefaults(*this);
+}
+
+void wxGLContextAttrs::EndList()
+{
+ wxGLBackend::Get().EndList(*this);
+}
+
+// ----------------------------------------------------------------------------
+// wxGLAttributes: Visual/FBconfig attributes
+// ----------------------------------------------------------------------------
+
+wxGLAttributes& wxGLAttributes::RGBA()
+{
+ return wxGLBackend::Get().RGBA(*this);
+}
+
+wxGLAttributes& wxGLAttributes::BufferSize(int val)
+{
+ return wxGLBackend::Get().BufferSize(*this, val);
+}
+
+wxGLAttributes& wxGLAttributes::Level(int val)
+{
+ return wxGLBackend::Get().Level(*this, val);
+}
+
+wxGLAttributes& wxGLAttributes::DoubleBuffer()
+{
+ return wxGLBackend::Get().DoubleBuffer(*this);
+}
+
+wxGLAttributes& wxGLAttributes::Stereo()
+{
+ return wxGLBackend::Get().Stereo(*this);
+}
+
+wxGLAttributes& wxGLAttributes::AuxBuffers(int val)
+{
+ return wxGLBackend::Get().AuxBuffers(*this, val);
+}
+
+wxGLAttributes& wxGLAttributes::MinRGBA(int mRed, int mGreen, int mBlue, int mAlpha)
+{
+ return wxGLBackend::Get().MinRGBA(*this, mRed, mGreen, mBlue, mAlpha);
+}
+
+wxGLAttributes& wxGLAttributes::Depth(int val)
+{
+ return wxGLBackend::Get().Depth(*this, val);
+}
+
+wxGLAttributes& wxGLAttributes::Stencil(int val)
+{
+ return wxGLBackend::Get().Stencil(*this, val);
+}
+
+wxGLAttributes& wxGLAttributes::MinAcumRGBA(int mRed, int mGreen, int mBlue, int mAlpha)
+{
+ return wxGLBackend::Get().MinAcumRGBA(*this, mRed, mGreen, mBlue, mAlpha);
+}
+
+wxGLAttributes& wxGLAttributes::SampleBuffers(int val)
+{
+ return wxGLBackend::Get().SampleBuffers(*this, val);
+}
+
+wxGLAttributes& wxGLAttributes::Samplers(int val)
+{
+ return wxGLBackend::Get().Samplers(*this, val);
+}
+
+wxGLAttributes& wxGLAttributes::FrameBuffersRGB()
+{
+ return wxGLBackend::Get().FrameBuffersRGB(*this);
+}
+
+void wxGLAttributes::EndList()
+{
+ wxGLBackend::Get().EndList(*this);
+}
+
+wxGLAttributes& wxGLAttributes::PlatformDefaults()
+{
+ return wxGLBackend::Get().PlatformDefaults(*this);
+}
+
+// ----------------------------------------------------------------------------
+// wxGLContext
+// ----------------------------------------------------------------------------
+
+wxIMPLEMENT_CLASS(wxGLContext, wxObject);
+
+wxGLBackend* wxGLBackend::ms_instance = nullptr;
+
+#ifdef wxHAS_EGL
+
+static bool wxGLBackendPreferGLX = false;
+
+/* static */
+void wxGLBackend::PreferGLX()
+{
+ wxASSERT_MSG( !ms_instance,
+ "PreferGLX() called too late and will have no effect" );
+
+ wxGLBackendPreferGLX = true;
+}
+#endif // wxHAS_EGL
+
+/* static */
+wxGLBackend* wxGLBackend::Init()
+{
+#ifdef wxHAS_EGL
+ // Only EGL can be used when using Wayland, so ignore calls to PreferGLX()
+ // and system option in that case.
+ //
+ // It is unfortunate that we need to call wxGTK-specific functions from
+ // this code which is shared by wxGTK and wxX11, but there is no way to
+ // virtualize it, notably we can't do it at wxGLCanvas level because it may
+ // be already too late: for example, the backend has to be already
+ // available for attributes creation.
+#if defined(__WXGTK3__) && defined(GDK_WINDOWING_WAYLAND)
+ if ( wxGTKImpl::IsWayland(gdk_display_get_default()) )
+ return &wxGLBackendEGL::Get();
+#endif // GTK 3 with Wayland
+
+ if ( !(wxGLBackendPreferGLX || wxSystemOptions::IsFalse("opengl.egl")) )
+ return &wxGLBackendEGL::Get();
+#endif // wxHAS_EGL
+
+ return &wxGLBackendX11::Get();
+}
+
+wxGLContext::wxGLContext(wxGLCanvas *win,
+ const wxGLContext *other,
+ const wxGLContextAttrs *ctxAttrs)
+ : m_impl(wxGLBackend::Get().CreateContextImpl(win, other, ctxAttrs))
+{
+ m_isOk = m_impl && m_impl->IsOK();
+}
+
+wxGLContext::~wxGLContext() = default;
+
+bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
+{
+ return IsOK() && m_impl->SetCurrent(win);
+}
+
+/* static */
+void wxGLContextBase::ClearCurrent()
+{
+ wxGLBackend::Get().ClearCurrentContext();
+}
+
+// ----------------------------------------------------------------------------
+// wxGLCanvasUnix
+// ----------------------------------------------------------------------------
+
+wxGLCanvasUnix::wxGLCanvasUnix()
+ : m_impl(wxGLBackend::Get().CreateCanvasImpl(this))
+{
+}
+
+wxGLCanvasUnix::~wxGLCanvasUnix() = default;
+
+bool wxGLCanvasUnix::InitVisual(const wxGLAttributes& dispAttrs)
+{
+ return m_impl->InitVisual(dispAttrs);
+}
+
+bool wxGLCanvasUnix::SwapBuffers()
+{
+ return m_impl->SwapBuffers();
+}
+
+bool wxGLCanvasUnix::IsShownOnScreen() const
+{
+ return m_impl->HasWindow() && wxGLCanvasBase::IsShownOnScreen();
+}
+
+void* wxGLCanvasUnix::GetXVisualInfo() const
+{
+ return m_impl->GetXVisualInfo();
+}
+
+void wxGLCanvasUnix::CallOnRealized()
+{
+ m_impl->OnRealized();
+}
+
+/* static */
+void wxGLCanvasUnix::PreferGLX()
+{
+#ifdef wxHAS_EGL
+ wxGLBackend::PreferGLX();
+#endif // wxHAS_EGL
+}
+
+/* static */
+bool wxGLCanvasUnix::GetEGLVersion(int* major, int* minor)
+{
+ return wxGLBackend::Get().GetEGLVersion(major, minor);
+}
+
+/* static */
+int wxGLCanvasUnix::GetGLXVersion()
+{
+ return wxGLBackend::Get().GetGLXVersion();
+}
+
+/* static */
+bool wxGLCanvasUnix::IsGLXMultiSampleAvailable()
+{
+ return wxGLBackend::Get().IsGLXMultiSampleAvailable();
+}
+
+/* static */
+bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
+{
+ return wxGLBackend::Get().IsExtensionSupported(extension);
+}
+
+/* static */
+bool wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs)
+{
+ return wxGLBackend::Get().IsDisplaySupported(dispAttrs);
+}
+
+/* static */
+bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
+{
+ wxGLAttributes dispAttrs;
+ ParseAttribList(attribList, dispAttrs);
+
+ return IsDisplaySupported(dispAttrs);
+}
+
+// ----------------------------------------------------------------------------
+// wxGLApp
+// ----------------------------------------------------------------------------
+
+bool wxGLApp::InitGLVisual(const int* attribList)
+{
+ return wxGLBackend::Get().InitDefaultVisualInfo(attribList);
+}
+
+void* wxGLApp::GetXVisualInfo()
+{
+ return wxGLBackend::Get().GetDefaultVisualInfo();
+}
+
+int wxGLApp::OnExit()
+{
+ wxGLBackend::Get().FreeDefaultVisualInfo();
+
+ return wxGLAppBase::OnExit();
+}
diff --git a/src/unix/glegl.cpp b/src/unix/glegl.cpp
index 854b2b7d77..e9b7709930 100644
--- a/src/unix/glegl.cpp
+++ b/src/unix/glegl.cpp
@@ -1,6 +1,7 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/unix/glegl.cpp
-// Purpose: code common to all EGL-based wxGLCanvas implementations
+// Purpose: EGL-based wxGLCanvas implementation for wxGTK (this file is
+// in src/unix subdirectory only for historical reasons)
// Author: Scott Talbert
// Created: 2017-12-26
// Copyright: (c) 2017 Scott Talbert
@@ -18,9 +19,12 @@
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
-#if wxUSE_GLCANVAS && wxUSE_GLCANVAS_EGL
+#if wxUSE_GLCANVAS && defined(wxHAS_EGL)
#include "wx/glcanvas.h"
+#include "wx/unix/private/glegl.h"
+
+#include "wx/private/make_unique.h"
#ifndef WX_PRECOMP
#include "wx/log.h"
@@ -32,9 +36,6 @@
#include
#endif
-#include
-#include
-
#include
namespace
@@ -42,6 +43,9 @@ namespace
constexpr const char* TRACE_EGL = "glegl";
+// It's ok to have this global variable because its ctor and dtor are trivial.
+wxGLBackendEGL wxGLBackendEGL_instance;
+
// EGL version initialized by InitConfig().
EGLint gs_eglMajor = 0;
EGLint gs_eglMinor = 0;
@@ -53,238 +57,231 @@ EGLint gs_eglMinor = 0;
// ----------------------------------------------------------------------------
// EGL specific values
-wxGLContextAttrs& wxGLContextAttrs::CoreProfile()
+wxGLContextAttrs& wxGLBackendEGL::CoreProfile(wxGLContextAttrs& attrs)
{
- AddAttribBits(EGL_CONTEXT_OPENGL_PROFILE_MASK,
+ attrs.AddAttribBits(EGL_CONTEXT_OPENGL_PROFILE_MASK,
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
- return *this;
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::MajorVersion(int val)
+wxGLContextAttrs& wxGLBackendEGL::MajorVersion(wxGLContextAttrs& attrs, int val)
{
if ( val > 0 )
{
- AddAttribute(EGL_CONTEXT_MAJOR_VERSION);
- AddAttribute(val);
+ attrs.AddAttribute(EGL_CONTEXT_MAJOR_VERSION);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::MinorVersion(int val)
+wxGLContextAttrs& wxGLBackendEGL::MinorVersion(wxGLContextAttrs& attrs, int val)
{
if ( val >= 0 )
{
- AddAttribute(EGL_CONTEXT_MINOR_VERSION);
- AddAttribute(val);
+ attrs.AddAttribute(EGL_CONTEXT_MINOR_VERSION);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::CompatibilityProfile()
+wxGLContextAttrs& wxGLBackendEGL::CompatibilityProfile(wxGLContextAttrs& attrs)
{
- AddAttribBits(EGL_CONTEXT_OPENGL_PROFILE_MASK,
+ attrs.AddAttribBits(EGL_CONTEXT_OPENGL_PROFILE_MASK,
EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
- return *this;
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::ForwardCompatible()
+wxGLContextAttrs& wxGLBackendEGL::ForwardCompatible(wxGLContextAttrs& attrs)
{
- AddAttribute(EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE);
- AddAttribute(EGL_TRUE);
- return *this;
+ attrs.AddAttribute(EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE);
+ attrs.AddAttribute(EGL_TRUE);
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::ES2()
+wxGLContextAttrs& wxGLBackendEGL::ES2(wxGLContextAttrs& attrs)
{
- useES = true;
- return *this;
+ attrs.useES = true;
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::DebugCtx()
+wxGLContextAttrs& wxGLBackendEGL::DebugCtx(wxGLContextAttrs& attrs)
{
- AddAttribute(EGL_CONTEXT_OPENGL_DEBUG);
- AddAttribute(EGL_TRUE);
- return *this;
+ attrs.AddAttribute(EGL_CONTEXT_OPENGL_DEBUG);
+ attrs.AddAttribute(EGL_TRUE);
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::Robust()
+wxGLContextAttrs& wxGLBackendEGL::Robust(wxGLContextAttrs& attrs)
{
- AddAttribute(EGL_CONTEXT_OPENGL_ROBUST_ACCESS);
- AddAttribute(EGL_TRUE);
- return *this;
+ attrs.AddAttribute(EGL_CONTEXT_OPENGL_ROBUST_ACCESS);
+ attrs.AddAttribute(EGL_TRUE);
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::NoResetNotify()
+wxGLContextAttrs& wxGLBackendEGL::NoResetNotify(wxGLContextAttrs& attrs)
{
- AddAttribute(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY);
- AddAttribute(EGL_NO_RESET_NOTIFICATION);
- return *this;
+ attrs.AddAttribute(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY);
+ attrs.AddAttribute(EGL_NO_RESET_NOTIFICATION);
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::LoseOnReset()
+wxGLContextAttrs& wxGLBackendEGL::LoseOnReset(wxGLContextAttrs& attrs)
{
- AddAttribute(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY);
- AddAttribute(EGL_LOSE_CONTEXT_ON_RESET);
- return *this;
+ attrs.AddAttribute(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY);
+ attrs.AddAttribute(EGL_LOSE_CONTEXT_ON_RESET);
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::ResetIsolation()
+wxGLContextAttrs& wxGLBackendEGL::ResetIsolation(wxGLContextAttrs& attrs)
{
- return *this;
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::ReleaseFlush(int)
+wxGLContextAttrs& wxGLBackendEGL::ReleaseFlush(wxGLContextAttrs& attrs, int)
{
- return *this;
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::PlatformDefaults()
+wxGLContextAttrs& wxGLBackendEGL::PlatformDefaults(wxGLContextAttrs& attrs)
{
- return *this;
-}
-
-void wxGLContextAttrs::EndList()
-{
- AddAttribute(EGL_NONE);
+ return attrs;
}
// ----------------------------------------------------------------------------
// wxGLAttributes: Visual/FBconfig attributes
// ----------------------------------------------------------------------------
-wxGLAttributes& wxGLAttributes::RGBA()
+wxGLAttributes& wxGLBackendEGL::RGBA(wxGLAttributes& attrs)
{
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::BufferSize(int val)
+wxGLAttributes& wxGLBackendEGL::BufferSize(wxGLAttributes& attrs, int val)
{
if ( val >= 0 )
{
- AddAttribute(EGL_BUFFER_SIZE);
- AddAttribute(val);
+ attrs.AddAttribute(EGL_BUFFER_SIZE);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::Level(int val)
+wxGLAttributes& wxGLBackendEGL::Level(wxGLAttributes& attrs, int val)
{
- AddAttribute(EGL_LEVEL);
- AddAttribute(val);
- return *this;
+ attrs.AddAttribute(EGL_LEVEL);
+ attrs.AddAttribute(val);
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::DoubleBuffer()
+wxGLAttributes& wxGLBackendEGL::DoubleBuffer(wxGLAttributes& attrs)
{
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::Stereo()
+wxGLAttributes& wxGLBackendEGL::Stereo(wxGLAttributes& attrs)
{
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::AuxBuffers(int)
+wxGLAttributes& wxGLBackendEGL::AuxBuffers(wxGLAttributes& attrs, int)
{
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::MinRGBA(int mRed, int mGreen, int mBlue, int mAlpha)
+wxGLAttributes& wxGLBackendEGL::MinRGBA(wxGLAttributes& attrs, int mRed, int mGreen, int mBlue, int mAlpha)
{
if ( mRed >= 0)
{
- AddAttribute(EGL_RED_SIZE);
- AddAttribute(mRed);
+ attrs.AddAttribute(EGL_RED_SIZE);
+ attrs.AddAttribute(mRed);
}
if ( mGreen >= 0)
{
- AddAttribute(EGL_GREEN_SIZE);
- AddAttribute(mGreen);
+ attrs.AddAttribute(EGL_GREEN_SIZE);
+ attrs.AddAttribute(mGreen);
}
if ( mBlue >= 0)
{
- AddAttribute(EGL_BLUE_SIZE);
- AddAttribute(mBlue);
+ attrs.AddAttribute(EGL_BLUE_SIZE);
+ attrs.AddAttribute(mBlue);
}
if ( mAlpha >= 0)
{
- AddAttribute(EGL_ALPHA_SIZE);
- AddAttribute(mAlpha);
+ attrs.AddAttribute(EGL_ALPHA_SIZE);
+ attrs.AddAttribute(mAlpha);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::Depth(int val)
+wxGLAttributes& wxGLBackendEGL::Depth(wxGLAttributes& attrs, int val)
{
if ( val >= 0 )
{
- AddAttribute(EGL_DEPTH_SIZE);
- AddAttribute(val);
+ attrs.AddAttribute(EGL_DEPTH_SIZE);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::Stencil(int val)
+wxGLAttributes& wxGLBackendEGL::Stencil(wxGLAttributes& attrs, int val)
{
if ( val >= 0 )
{
- AddAttribute(EGL_STENCIL_SIZE);
- AddAttribute(val);
+ attrs.AddAttribute(EGL_STENCIL_SIZE);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::MinAcumRGBA(int, int, int, int)
+wxGLAttributes& wxGLBackendEGL::MinAcumRGBA(wxGLAttributes& attrs, int, int, int, int)
{
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::SampleBuffers(int val)
+wxGLAttributes& wxGLBackendEGL::SampleBuffers(wxGLAttributes& attrs, int val)
{
if ( val >= 0 )
{
- AddAttribute(EGL_SAMPLE_BUFFERS);
- AddAttribute(val);
+ attrs.AddAttribute(EGL_SAMPLE_BUFFERS);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::Samplers(int val)
+wxGLAttributes& wxGLBackendEGL::Samplers(wxGLAttributes& attrs, int val)
{
if ( val >= 0 )
{
- AddAttribute(EGL_SAMPLES);
- AddAttribute(val);
+ attrs.AddAttribute(EGL_SAMPLES);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::FrameBuffersRGB()
+wxGLAttributes& wxGLBackendEGL::FrameBuffersRGB(wxGLAttributes& attrs)
{
- return *this;
+ return attrs;
}
-void wxGLAttributes::EndList()
-{
- AddAttribute(EGL_NONE);
-}
-
-wxGLAttributes& wxGLAttributes::PlatformDefaults()
+wxGLAttributes& wxGLBackendEGL::PlatformDefaults(wxGLAttributes& attrs)
{
// No EGL specific values
- return *this;
+ return attrs;
+}
+
+void wxGLBackendEGL::EndList(wxGLAttribsBase& attrs)
+{
+ attrs.AddAttribute(EGL_NONE);
}
// ============================================================================
-// wxGLContext implementation
+// wxGLContextEGL implementation
// ============================================================================
-wxIMPLEMENT_CLASS(wxGLContext, wxObject);
-
-wxGLContext::wxGLContext(wxGLCanvas *win,
- const wxGLContext *other,
- const wxGLContextAttrs *ctxAttrs)
+wxGLContextEGL::wxGLContextEGL(wxGLCanvas *win,
+ const wxGLContext *other,
+ const wxGLContextAttrs *ctxAttrs)
: m_glContext(nullptr)
{
// Fall back to OpenGL context parameters set at wxGLCanvas ctor if any.
@@ -301,11 +298,14 @@ wxGLContext::wxGLContext(wxGLCanvas *win,
return;
}
- EGLConfig fbc = win->GetEGLConfig();
+ EGLConfig fbc = static_cast(win->GetImpl())->GetEGLConfig();
wxCHECK_RET( fbc, "Invalid EGLConfig for OpenGL" );
+ EGLContext otherCtx = EGL_NO_CONTEXT;
+ if ( other )
+ otherCtx = static_cast(other->GetImpl())->m_glContext;
m_glContext = eglCreateContext(wxGLCanvasEGL::GetDisplay(), fbc,
- other ? other->m_glContext : EGL_NO_CONTEXT,
+ otherCtx,
attrs.GetGLAttrs());
if ( !m_glContext )
@@ -314,28 +314,29 @@ wxGLContext::wxGLContext(wxGLCanvas *win,
m_isOk = true;
}
-wxGLContext::~wxGLContext()
+wxGLContextEGL::~wxGLContextEGL()
{
if ( !m_glContext )
return;
if ( m_glContext == eglGetCurrentContext() )
- ClearCurrent();
+ wxGLBackendEGL_instance.ClearCurrentContext();
eglDestroyContext(wxGLCanvasEGL::GetDisplay(), m_glContext);
}
-bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
+bool wxGLContextEGL::SetCurrent(const wxGLCanvas& win) const
{
if ( !m_glContext )
return false;
- return eglMakeCurrent(win.GetEGLDisplay(), win.GetEGLSurface(),
- win.GetEGLSurface(), m_glContext);
+ auto const winEGL = static_cast(win.GetImpl());
+
+ return eglMakeCurrent(winEGL->GetEGLDisplay(), winEGL->GetEGLSurface(),
+ winEGL->GetEGLSurface(), m_glContext);
}
-/* static */
-void wxGLContextBase::ClearCurrent()
+void wxGLBackendEGL::ClearCurrentContext()
{
eglMakeCurrent(wxGLCanvasEGL::GetDisplay(), EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -421,8 +422,8 @@ void wxGLCanvasEGL::OnWLFrameCallback()
m_readyToDraw = true;
g_clear_pointer(&m_wlFrameCallbackHandler, wl_callback_destroy);
- SendSizeEvent();
- gtk_widget_queue_draw(m_wxwindow);
+ m_canvas->SendSizeEvent();
+ gtk_widget_queue_draw(m_canvas->m_wxwindow);
#endif // GDK_WINDOWING_WAYLAND
}
@@ -439,7 +440,7 @@ void wxGLCanvasEGL::UpdateSubsurfacePosition()
}
int x, y;
- gdk_window_get_origin(GTKGetDrawingWindow(), &x, &y);
+ gdk_window_get_origin(m_canvas->GTKGetDrawingWindow(), &x, &y);
wl_subsurface_set_position(m_wlSubsurface, x, y);
}
@@ -449,8 +450,8 @@ void wxGLCanvasEGL::UpdateSubsurfacePosition()
void wxEGLUpdateGeometry(GtkWidget* widget, 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);
+ wl_egl_window_resize(win->m_wlEGLWindow, win->m_canvas->m_width * scale,
+ win->m_canvas->m_height * scale, 0, 0);
win->UpdateSubsurfacePosition();
@@ -561,7 +562,7 @@ EGLSurface wxGLCanvasEGL::CallCreatePlatformWindowSurface(void *window) const
{
s_extFuncInitialized = true;
- if ( IsExtensionSupported("EGL_EXT_platform_base") )
+ if ( wxGLBackendEGL_instance.IsExtensionSupported("EGL_EXT_platform_base") )
{
s_eglCreatePlatformWindowSurfaceEXT = reinterpret_cast(
eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"));
@@ -582,16 +583,16 @@ EGLSurface wxGLCanvasEGL::CallCreatePlatformWindowSurface(void *window) const
}
}
-bool wxGLCanvasEGL::CreateSurface()
+void wxGLCanvasEGL::OnRealized()
{
m_display = GetDisplay();
if ( m_display == EGL_NO_DISPLAY )
{
wxFAIL_MSG("Unable to get EGL Display");
- return false;
+ return;
}
- GdkWindow *window = GTKGetDrawingWindow();
+ GdkWindow *window = m_canvas->GTKGetDrawingWindow();
#ifdef GDK_WINDOWING_X11
if (wxGTKImpl::IsX11(window))
{
@@ -612,7 +613,7 @@ bool wxGLCanvasEGL::CreateSurface()
{
// Already created (can happen when the canvas is un-realized then
// re-realized, for example, when the canvas is re-parented)
- return true;
+ return;
}
int w = gdk_window_get_width(window);
@@ -624,7 +625,7 @@ bool wxGLCanvasEGL::CreateSurface()
if ( !m_wlCompositor || !m_wlSubcompositor )
{
wxFAIL_MSG("Invalid Wayland compositor or subcompositor");
- return false;
+ return;
}
m_wlSurface = wl_compositor_create_surface(m_wlCompositor);
m_wlRegion = wl_compositor_create_region(m_wlCompositor);
@@ -635,16 +636,18 @@ bool wxGLCanvasEGL::CreateSurface()
h * scale);
m_surface = CallCreatePlatformWindowSurface(m_wlEGLWindow);
+ GtkWidget* const widget = m_canvas->m_widget;
+
// We need to use "map-event" instead of "map" to ensure that the
// widget's underlying Wayland surface has been created.
// Otherwise, gdk_wayland_window_get_wl_surface may return nullptr,
// for example when hiding then showing a window containing a canvas.
- gtk_widget_add_events(m_widget, GDK_STRUCTURE_MASK);
- g_signal_connect(m_widget, "map-event",
+ gtk_widget_add_events(widget, GDK_STRUCTURE_MASK);
+ g_signal_connect(widget, "map-event",
G_CALLBACK(gtk_glcanvas_map_callback), this);
// However, note the use of "unmap" instead of the later "unmap-event"
// Not unmapping the canvas as soon as possible causes problems when reparenting
- g_signal_connect(m_widget, "unmap",
+ g_signal_connect(widget, "unmap",
G_CALLBACK(gtk_glcanvas_unmap_callback), this);
// We connect to "size-allocate" to update the position of the
@@ -653,9 +656,9 @@ bool wxGLCanvasEGL::CreateSurface()
// "notify::scale-factor" to catch scale changes, which is especially
// important initially, as we don't get a "size-allocate" with the
// correct scale when the window is created.
- g_signal_connect(m_widget, "size-allocate",
+ g_signal_connect(widget, "size-allocate",
G_CALLBACK(gtk_glcanvas_size_callback), this);
- g_signal_connect(m_widget, "notify::scale-factor",
+ g_signal_connect(widget, "notify::scale-factor",
G_CALLBACK (gtk_glcanvas_scale_factor_notify), this);
}
#endif
@@ -663,10 +666,8 @@ bool wxGLCanvasEGL::CreateSurface()
if ( m_surface == EGL_NO_SURFACE )
{
wxFAIL_MSG("Unable to create EGL surface");
- return false;
+ return;
}
-
- return true;
}
wxGLCanvasEGL::~wxGLCanvasEGL()
@@ -693,12 +694,12 @@ void wxGLCanvasEGL::CreateWaylandSubsurface()
// Not ignoring either of the two scenarios will likely cause the subsurface
// to be created twice, leading to a crash due to a Wayland protocol error
// See https://github.com/wxWidgets/wxWidgets/issues/23961
- if ( !gtk_widget_get_mapped(m_widget) || m_wlSubsurface )
+ if ( !gtk_widget_get_mapped(m_canvas->m_widget) || m_wlSubsurface )
{
return;
}
- GdkWindow *window = GTKGetDrawingWindow();
+ GdkWindow *window = m_canvas->GTKGetDrawingWindow();
struct wl_surface *surface = gdk_wayland_window_get_wl_surface(window);
m_wlSubsurface = wl_subcompositor_get_subsurface(m_wlSubcompositor,
@@ -727,12 +728,12 @@ void wxGLCanvasEGL::DestroyWaylandSubsurface()
// working with GL attributes
// ----------------------------------------------------------------------------
-/* static */
-bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
+bool wxGLBackendEGL::IsExtensionSupported(const char *extension)
{
EGLDisplay dpy = wxGLCanvasEGL::GetDisplay();
- return IsExtensionInList(eglQueryString(dpy, EGL_EXTENSIONS), extension);
+ return wxGLCanvasBase::IsExtensionInList(eglQueryString(dpy, EGL_EXTENSIONS),
+ extension);
}
@@ -769,11 +770,6 @@ EGLConfig wxGLCanvasEGL::InitConfig(const wxGLAttributes& dispAttrs)
return nullptr;
}
- if ( !eglBindAPI(EGL_OPENGL_API) ) {
- wxFAIL_MSG("eglBindAPI failed");
- return nullptr;
- }
-
EGLint numConfigs = 0;
// Check if we need to filter out the configs using alpha, as getting one
@@ -837,44 +833,37 @@ EGLConfig wxGLCanvasEGL::InitConfig(const wxGLAttributes& dispAttrs)
return configs.front();
}
-/* static */
-bool wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs)
+bool wxGLBackendEGL::IsDisplaySupported(const wxGLAttributes& dispAttrs)
{
return wxGLCanvasEGL::InitConfig(dispAttrs) != nullptr;
}
-/* static */
-bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
-{
- wxGLAttributes dispAttrs;
- ParseAttribList(attribList, dispAttrs);
-
- return IsDisplaySupported(dispAttrs);
-}
-
// ----------------------------------------------------------------------------
// default visual management
// ----------------------------------------------------------------------------
-EGLConfig wxGLCanvasEGL::ms_glEGLConfig = nullptr;
+static EGLConfig wxDefaultEGLConfig = nullptr;
-/* static */
-bool wxGLCanvasEGL::InitDefaultConfig(const int *attribList)
+bool wxGLBackendEGL::InitDefaultVisualInfo(const int *attribList)
{
- FreeDefaultConfig();
wxGLAttributes dispAttrs;
- ParseAttribList(attribList, dispAttrs);
+ wxGLCanvasBase::ParseAttribList(attribList, dispAttrs);
- ms_glEGLConfig = InitConfig(dispAttrs);
- return ms_glEGLConfig != nullptr;
+ wxDefaultEGLConfig = wxGLCanvasEGL::InitConfig(dispAttrs);
+ return wxDefaultEGLConfig != nullptr;
}
-/* static */
-void wxGLCanvasEGL::FreeDefaultConfig()
+void wxGLBackendEGL::FreeDefaultVisualInfo()
{
- ms_glEGLConfig = nullptr;
+ wxDefaultEGLConfig = nullptr;
}
+void* wxGLBackendEGL::GetDefaultVisualInfo()
+{
+ return wxDefaultEGLConfig;
+}
+
+
// ----------------------------------------------------------------------------
// other GL methods
// ----------------------------------------------------------------------------
@@ -908,13 +897,13 @@ bool wxGLCanvasEGL::SwapBuffers()
}
}
- GdkWindow* const window = GTKGetDrawingWindow();
+ GdkWindow* const window = m_canvas->GTKGetDrawingWindow();
#ifdef GDK_WINDOWING_X11
if (wxGTKImpl::IsX11(window))
{
// TODO: We need to check if it's really shown on screen, i.e. if it's
// not completely occluded even if it hadn't been explicitly hidden.
- if ( !IsShownOnScreen() )
+ if ( !m_canvas->IsShownOnScreen() )
{
// Trying to draw on a hidden window is useless.
wxLogTrace(TRACE_EGL, "Window %p is hidden, not drawing", this);
@@ -940,15 +929,15 @@ bool wxGLCanvasEGL::SwapBuffers()
return eglSwapBuffers(m_display, m_surface);
}
-bool wxGLCanvasEGL::IsShownOnScreen() const
+bool wxGLCanvasEGL::HasWindow() const
{
wxDisplayInfo info = wxGetDisplayInfo();
switch ( info.type )
{
case wxDisplayX11:
- return GetXWindow() && wxGLCanvasBase::IsShownOnScreen();
+ return m_canvas->GetXWindow();
case wxDisplayWayland:
- return m_wlSubsurface && wxGLCanvasBase::IsShownOnScreen();
+ return m_wlSubsurface;
case wxDisplayNone:
break;
}
@@ -956,5 +945,50 @@ bool wxGLCanvasEGL::IsShownOnScreen() const
return false;
}
-#endif // wxUSE_GLCANVAS && wxUSE_GLCANVAS_EGL
+// ----------------------------------------------------------------------------
+// wxGLBackendEGL
+// ----------------------------------------------------------------------------
+/* static */
+wxGLBackend& wxGLBackendEGL::Get()
+{
+ return wxGLBackendEGL_instance;
+}
+
+std::unique_ptr
+wxGLBackendEGL::CreateContextImpl(wxGLCanvas* win,
+ const wxGLContext* other,
+ const wxGLContextAttrs* ctxAttrs)
+{
+ return std::make_unique(win, other, ctxAttrs);
+}
+
+std::unique_ptr
+wxGLBackendEGL::CreateCanvasImpl(wxGLCanvasUnix* canvas)
+{
+ return std::make_unique(canvas);
+}
+
+bool wxGLBackendEGL::GetEGLVersion(int* major, int* minor)
+{
+ if ( major )
+ *major = gs_eglMajor;
+ if ( minor )
+ *minor = gs_eglMinor;
+
+ return true;
+}
+
+int wxGLBackendEGL::GetGLXVersion()
+{
+ // EGL doesn't have GLX version.
+ return 0;
+}
+
+bool wxGLBackendEGL::IsGLXMultiSampleAvailable()
+{
+ // EGL doesn't have GLX multisample extension.
+ return false;
+}
+
+#endif // wxUSE_GLCANVAS && defined(wxHAS_EGL)
diff --git a/src/unix/glx11.cpp b/src/unix/glx11.cpp
index f867c0b053..2b70aacba0 100644
--- a/src/unix/glx11.cpp
+++ b/src/unix/glx11.cpp
@@ -18,17 +18,19 @@
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
-#if wxUSE_GLCANVAS && !wxUSE_GLCANVAS_EGL
+#if wxUSE_GLCANVAS
#ifndef WX_PRECOMP
#include "wx/log.h"
#endif //WX_PRECOMP
#include "wx/glcanvas.h"
-#include
+#include "wx/unix/private/glx11.h"
#include "wx/unix/private/x11ptr.h"
+#include "wx/private/make_unique.h"
+
// IRIX headers call this differently
#ifdef __SGI__
#ifndef GLX_SAMPLE_BUFFERS_ARB
@@ -131,6 +133,9 @@ namespace
constexpr const char* TRACE_GLX = "glx";
+// It's ok to have this global variable because its ctor and dtor are trivial.
+wxGLBackendX11 wxGLBackendX11_instance;
+
} // anonymous namespace
// ----------------------------------------------------------------------------
@@ -138,121 +143,116 @@ constexpr const char* TRACE_GLX = "glx";
// ----------------------------------------------------------------------------
// GLX specific values
-wxGLContextAttrs& wxGLContextAttrs::CoreProfile()
+wxGLContextAttrs& wxGLBackendX11::CoreProfile(wxGLContextAttrs& attrs)
{
- AddAttribBits(GLX_CONTEXT_PROFILE_MASK_ARB,
+ attrs.AddAttribBits(GLX_CONTEXT_PROFILE_MASK_ARB,
GLX_CONTEXT_CORE_PROFILE_BIT_ARB);
- SetNeedsARB();
- return *this;
+ attrs.SetNeedsARB();
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::MajorVersion(int val)
+wxGLContextAttrs& wxGLBackendX11::MajorVersion(wxGLContextAttrs& attrs, int val)
{
if ( val > 0 )
{
- AddAttribute(GLX_CONTEXT_MAJOR_VERSION_ARB);
- AddAttribute(val);
+ attrs.AddAttribute(GLX_CONTEXT_MAJOR_VERSION_ARB);
+ attrs.AddAttribute(val);
if ( val >= 3 )
- SetNeedsARB();
+ attrs.SetNeedsARB();
}
- return *this;
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::MinorVersion(int val)
+wxGLContextAttrs& wxGLBackendX11::MinorVersion(wxGLContextAttrs& attrs, int val)
{
if ( val >= 0 )
{
- AddAttribute(GLX_CONTEXT_MINOR_VERSION_ARB);
- AddAttribute(val);
+ attrs.AddAttribute(GLX_CONTEXT_MINOR_VERSION_ARB);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::CompatibilityProfile()
+wxGLContextAttrs& wxGLBackendX11::CompatibilityProfile(wxGLContextAttrs& attrs)
{
- AddAttribBits(GLX_CONTEXT_PROFILE_MASK_ARB,
+ attrs.AddAttribBits(GLX_CONTEXT_PROFILE_MASK_ARB,
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
- SetNeedsARB();
- return *this;
+ attrs.SetNeedsARB();
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::ForwardCompatible()
+wxGLContextAttrs& wxGLBackendX11::ForwardCompatible(wxGLContextAttrs& attrs)
{
- AddAttribBits(GLX_CONTEXT_FLAGS_ARB,
+ attrs.AddAttribBits(GLX_CONTEXT_FLAGS_ARB,
GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
- SetNeedsARB();
- return *this;
+ attrs.SetNeedsARB();
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::ES2()
+wxGLContextAttrs& wxGLBackendX11::ES2(wxGLContextAttrs& attrs)
{
- AddAttribBits(GLX_CONTEXT_PROFILE_MASK_ARB,
+ attrs.AddAttribBits(GLX_CONTEXT_PROFILE_MASK_ARB,
GLX_CONTEXT_ES2_PROFILE_BIT_EXT);
- SetNeedsARB();
- return *this;
+ attrs.SetNeedsARB();
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::DebugCtx()
+wxGLContextAttrs& wxGLBackendX11::DebugCtx(wxGLContextAttrs& attrs)
{
- AddAttribBits(GLX_CONTEXT_FLAGS_ARB,
+ attrs.AddAttribBits(GLX_CONTEXT_FLAGS_ARB,
GLX_CONTEXT_DEBUG_BIT_ARB);
- SetNeedsARB();
- return *this;
+ attrs.SetNeedsARB();
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::Robust()
+wxGLContextAttrs& wxGLBackendX11::Robust(wxGLContextAttrs& attrs)
{
- AddAttribBits(GLX_CONTEXT_FLAGS_ARB,
+ attrs.AddAttribBits(GLX_CONTEXT_FLAGS_ARB,
GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB);
- SetNeedsARB();
- return *this;
+ attrs.SetNeedsARB();
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::NoResetNotify()
+wxGLContextAttrs& wxGLBackendX11::NoResetNotify(wxGLContextAttrs& attrs)
{
- AddAttribute(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
- AddAttribute(GLX_NO_RESET_NOTIFICATION_ARB);
- SetNeedsARB();
- return *this;
+ attrs.AddAttribute(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+ attrs.AddAttribute(GLX_NO_RESET_NOTIFICATION_ARB);
+ attrs.SetNeedsARB();
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::LoseOnReset()
+wxGLContextAttrs& wxGLBackendX11::LoseOnReset(wxGLContextAttrs& attrs)
{
- AddAttribute(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
- AddAttribute(GLX_LOSE_CONTEXT_ON_RESET_ARB);
- SetNeedsARB();
- return *this;
+ attrs.AddAttribute(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+ attrs.AddAttribute(GLX_LOSE_CONTEXT_ON_RESET_ARB);
+ attrs.SetNeedsARB();
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::ResetIsolation()
+wxGLContextAttrs& wxGLBackendX11::ResetIsolation(wxGLContextAttrs& attrs)
{
- AddAttribBits(GLX_CONTEXT_FLAGS_ARB,
+ attrs.AddAttribBits(GLX_CONTEXT_FLAGS_ARB,
GLX_CONTEXT_RESET_ISOLATION_BIT_ARB);
- SetNeedsARB();
- return *this;
+ attrs.SetNeedsARB();
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::ReleaseFlush(int val)
+wxGLContextAttrs& wxGLBackendX11::ReleaseFlush(wxGLContextAttrs& attrs, int val)
{
- AddAttribute(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB);
+ attrs.AddAttribute(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB);
if ( val == 1 )
- AddAttribute(GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
+ attrs.AddAttribute(GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
else
- AddAttribute(GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
- SetNeedsARB();
- return *this;
+ attrs.AddAttribute(GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
+ attrs.SetNeedsARB();
+ return attrs;
}
-wxGLContextAttrs& wxGLContextAttrs::PlatformDefaults()
+wxGLContextAttrs& wxGLBackendX11::PlatformDefaults(wxGLContextAttrs& attrs)
{
- renderTypeRGBA = true;
- x11Direct = true;
- return *this;
-}
-
-void wxGLContextAttrs::EndList()
-{
- AddAttribute(None);
+ attrs.renderTypeRGBA = true;
+ attrs.x11Direct = true;
+ return attrs;
}
// ----------------------------------------------------------------------------
@@ -272,173 +272,173 @@ void wxGLContextAttrs::EndList()
// - Boolean attributes such as GLX_DOUBLEBUFFER don't take values in the
// old version but must be followed by True or False in the new one.
-wxGLAttributes& wxGLAttributes::RGBA()
+wxGLAttributes& wxGLBackendX11::RGBA(wxGLAttributes& attrs)
{
- if ( wxGLCanvasX11::GetGLXVersion() >= 13 )
- AddAttribBits(GLX_RENDER_TYPE, GLX_RGBA_BIT);
+ if ( GetGLXVersion() >= 13 )
+ attrs.AddAttribBits(GLX_RENDER_TYPE, GLX_RGBA_BIT);
else
- AddAttribute(GLX_RGBA);
- return *this;
+ attrs.AddAttribute(GLX_RGBA);
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::BufferSize(int val)
+wxGLAttributes& wxGLBackendX11::BufferSize(wxGLAttributes& attrs, int val)
{
if ( val >= 0 )
{
- AddAttribute(GLX_BUFFER_SIZE);
- AddAttribute(val);
+ attrs.AddAttribute(GLX_BUFFER_SIZE);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::Level(int val)
+wxGLAttributes& wxGLBackendX11::Level(wxGLAttributes& attrs, int val)
{
- AddAttribute(GLX_LEVEL);
- AddAttribute(val);
- return *this;
+ attrs.AddAttribute(GLX_LEVEL);
+ attrs.AddAttribute(val);
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::DoubleBuffer()
+wxGLAttributes& wxGLBackendX11::DoubleBuffer(wxGLAttributes& attrs)
{
- AddAttribute(GLX_DOUBLEBUFFER);
- if ( wxGLCanvasX11::GetGLXVersion() >= 13 )
- AddAttribute(True);
- return *this;
+ attrs.AddAttribute(GLX_DOUBLEBUFFER);
+ if ( GetGLXVersion() >= 13 )
+ attrs.AddAttribute(True);
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::Stereo()
+wxGLAttributes& wxGLBackendX11::Stereo(wxGLAttributes& attrs)
{
- AddAttribute(GLX_STEREO);
- if ( wxGLCanvasX11::GetGLXVersion() >= 13 )
- AddAttribute(True);
- return *this;
+ attrs.AddAttribute(GLX_STEREO);
+ if ( GetGLXVersion() >= 13 )
+ attrs.AddAttribute(True);
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::AuxBuffers(int val)
+wxGLAttributes& wxGLBackendX11::AuxBuffers(wxGLAttributes& attrs, int val)
{
if ( val >= 0 )
{
- AddAttribute(GLX_AUX_BUFFERS);
- AddAttribute(val);
+ attrs.AddAttribute(GLX_AUX_BUFFERS);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::MinRGBA(int mRed, int mGreen, int mBlue, int mAlpha)
+wxGLAttributes& wxGLBackendX11::MinRGBA(wxGLAttributes& attrs, int mRed, int mGreen, int mBlue, int mAlpha)
{
if ( mRed >= 0)
{
- AddAttribute(GLX_RED_SIZE);
- AddAttribute(mRed);
+ attrs.AddAttribute(GLX_RED_SIZE);
+ attrs.AddAttribute(mRed);
}
if ( mGreen >= 0)
{
- AddAttribute(GLX_GREEN_SIZE);
- AddAttribute(mGreen);
+ attrs.AddAttribute(GLX_GREEN_SIZE);
+ attrs.AddAttribute(mGreen);
}
if ( mBlue >= 0)
{
- AddAttribute(GLX_BLUE_SIZE);
- AddAttribute(mBlue);
+ attrs.AddAttribute(GLX_BLUE_SIZE);
+ attrs.AddAttribute(mBlue);
}
if ( mAlpha >= 0)
{
- AddAttribute(GLX_ALPHA_SIZE);
- AddAttribute(mAlpha);
+ attrs.AddAttribute(GLX_ALPHA_SIZE);
+ attrs.AddAttribute(mAlpha);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::Depth(int val)
+wxGLAttributes& wxGLBackendX11::Depth(wxGLAttributes& attrs, int val)
{
if ( val >= 0 )
{
- AddAttribute(GLX_DEPTH_SIZE);
- AddAttribute(val);
+ attrs.AddAttribute(GLX_DEPTH_SIZE);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::Stencil(int val)
+wxGLAttributes& wxGLBackendX11::Stencil(wxGLAttributes& attrs, int val)
{
if ( val >= 0 )
{
- AddAttribute(GLX_STENCIL_SIZE);
- AddAttribute(val);
+ attrs.AddAttribute(GLX_STENCIL_SIZE);
+ attrs.AddAttribute(val);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::MinAcumRGBA(int mRed, int mGreen, int mBlue, int mAlpha)
+wxGLAttributes& wxGLBackendX11::MinAcumRGBA(wxGLAttributes& attrs, int mRed, int mGreen, int mBlue, int mAlpha)
{
if ( mRed >= 0)
{
- AddAttribute(GLX_ACCUM_RED_SIZE);
- AddAttribute(mRed);
+ attrs.AddAttribute(GLX_ACCUM_RED_SIZE);
+ attrs.AddAttribute(mRed);
}
if ( mGreen >= 0)
{
- AddAttribute(GLX_ACCUM_GREEN_SIZE);
- AddAttribute(mGreen);
+ attrs.AddAttribute(GLX_ACCUM_GREEN_SIZE);
+ attrs.AddAttribute(mGreen);
}
if ( mBlue >= 0)
{
- AddAttribute(GLX_ACCUM_BLUE_SIZE);
- AddAttribute(mBlue);
+ attrs.AddAttribute(GLX_ACCUM_BLUE_SIZE);
+ attrs.AddAttribute(mBlue);
}
if ( mAlpha >= 0)
{
- AddAttribute(GLX_ACCUM_ALPHA_SIZE);
- AddAttribute(mAlpha);
+ attrs.AddAttribute(GLX_ACCUM_ALPHA_SIZE);
+ attrs.AddAttribute(mAlpha);
}
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::SampleBuffers(int val)
+wxGLAttributes& wxGLBackendX11::SampleBuffers(wxGLAttributes& attrs, int val)
{
#ifdef GLX_SAMPLE_BUFFERS_ARB
- if ( val >= 0 && wxGLCanvasX11::IsGLXMultiSampleAvailable() )
+ if ( val >= 0 && IsGLXMultiSampleAvailable() )
{
- AddAttribute(GLX_SAMPLE_BUFFERS_ARB);
- AddAttribute(val);
+ attrs.AddAttribute(GLX_SAMPLE_BUFFERS_ARB);
+ attrs.AddAttribute(val);
}
#endif
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::Samplers(int val)
+wxGLAttributes& wxGLBackendX11::Samplers(wxGLAttributes& attrs, int val)
{
#ifdef GLX_SAMPLES_ARB
- if ( val >= 0 && wxGLCanvasX11::IsGLXMultiSampleAvailable() )
+ if ( val >= 0 && IsGLXMultiSampleAvailable() )
{
- AddAttribute(GLX_SAMPLES_ARB);
- AddAttribute(val);
+ attrs.AddAttribute(GLX_SAMPLES_ARB);
+ attrs.AddAttribute(val);
}
#endif
- return *this;
+ return attrs;
}
-wxGLAttributes& wxGLAttributes::FrameBuffersRGB()
+wxGLAttributes& wxGLBackendX11::FrameBuffersRGB(wxGLAttributes& attrs)
{
- AddAttribute(GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
- AddAttribute(True);
- return *this;
+ attrs.AddAttribute(GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
+ attrs.AddAttribute(True);
+ return attrs;
}
-void wxGLAttributes::EndList()
-{
- AddAttribute(None);
-}
-
-wxGLAttributes& wxGLAttributes::PlatformDefaults()
+wxGLAttributes& wxGLBackendX11::PlatformDefaults(wxGLAttributes& attrs)
{
// No GLX specific values
- return *this;
+ return attrs;
+}
+
+void wxGLBackendX11::EndList(wxGLAttribsBase& attrs)
+{
+ attrs.AddAttribute(None);
}
// ============================================================================
-// wxGLContext implementation
+// wxGLContextX11 implementation
// ============================================================================
static bool MakeCurrent(GLXDrawable drawable, GLXContext context);
@@ -451,39 +451,43 @@ static int CTXErrorHandler( Display* WXUNUSED(dpy), XErrorEvent* WXUNUSED(ev) )
return 0;
}
-wxIMPLEMENT_CLASS(wxGLContext, wxObject);
-
-wxGLContext::wxGLContext(wxGLCanvas *win,
- const wxGLContext *other,
- const wxGLContextAttrs *ctxAttrs)
+wxGLContextX11::wxGLContextX11(wxGLCanvas *win,
+ const wxGLContext *otherCtx,
+ const wxGLContextAttrs *ctxAttrs)
: m_glContext(nullptr)
{
- const int* contextAttribs = nullptr;
+ // We assume that all contexts in the program are of the same type, so the
+ // other context passed in must also be using wxGLContextX11.
+ auto const otherGLXContext =
+ otherCtx ? static_cast(otherCtx->GetImpl())->m_glContext
+ : None;
+
+ // The window must also be of the appropriate type.
+ auto const winX11 = static_cast(win->GetImpl());
+
+ // Fall back to OpenGL context parameters set at wxGLCanvas ctor if any.
+ const wxGLContextAttrs& attrs = ctxAttrs ? *ctxAttrs
+ : win->GetGLCTXAttrs();
+
+ const int* const contextAttribs = attrs.GetGLAttrs();
Bool x11Direct = True;
int renderType = GLX_RGBA_TYPE;
bool needsARB = false;
- if ( ctxAttrs )
+ // Note that we don't use default values from GetGLCTXAttrs() here unless
+ // we have some explicit attributes specified, as the default values differ
+ // from PlatformDefaults() ones, which are used just above.
+ if ( contextAttribs )
{
- contextAttribs = ctxAttrs->GetGLAttrs();
- x11Direct = ctxAttrs->x11Direct;
- renderType = ctxAttrs->renderTypeRGBA ? GLX_RGBA_TYPE : GLX_COLOR_INDEX_TYPE;
- needsARB = ctxAttrs->NeedsARB();
+ renderType = attrs.renderTypeRGBA ? GLX_RGBA_TYPE : GLX_COLOR_INDEX_TYPE;
+ x11Direct = attrs.x11Direct ? True : False;
+ needsARB = attrs.NeedsARB();
}
- else if ( win->GetGLCTXAttrs().GetGLAttrs() )
- {
- // If OpenGL context parameters were set at wxGLCanvas ctor, get them now
- contextAttribs = win->GetGLCTXAttrs().GetGLAttrs();
- x11Direct = win->GetGLCTXAttrs().x11Direct;
- renderType = win->GetGLCTXAttrs().renderTypeRGBA ? GLX_RGBA_TYPE : GLX_COLOR_INDEX_TYPE;
- needsARB = win->GetGLCTXAttrs().NeedsARB();
- }
- // else use GPU driver defaults and x11Direct renderType ones
m_isOk = false;
Display* dpy = wxGetX11Display();
- XVisualInfo* vi = static_cast(win->GetXVisualInfo());
+ XVisualInfo* vi = static_cast(winX11->GetXVisualInfo());
wxCHECK_RET( vi, "invalid visual for OpenGL" );
// We need to create a temporary context to get the
@@ -491,7 +495,7 @@ wxGLContext::wxGLContext(wxGLCanvas *win,
GLXContext tempContext = glXCreateContext(dpy, vi, nullptr, x11Direct);
wxCHECK_RET(tempContext, "glXCreateContext failed" );
- GLXFBConfig* const fbc = win->GetGLXFBConfig();
+ GLXFBConfig* const fbc = winX11->GetGLXFBConfig();
PFNGLXCREATECONTEXTATTRIBSARBPROC wx_glXCreateContextAttribsARB = 0;
if (fbc)
{
@@ -516,7 +520,7 @@ wxGLContext::wxGLContext(wxGLCanvas *win,
if ( wx_glXCreateContextAttribsARB )
{
m_glContext = wx_glXCreateContextAttribsARB( dpy, fbc[0],
- other ? other->m_glContext : None,
+ otherGLXContext,
x11Direct, contextAttribs );
// Some old hardware may accept the use of this ARB, but may fail.
@@ -535,13 +539,13 @@ wxGLContext::wxGLContext(wxGLCanvas *win,
if (fbc)
{
m_glContext = glXCreateNewContext( dpy, fbc[0], renderType,
- other ? other->m_glContext : None,
+ otherGLXContext,
x11Direct );
}
else // GLX <= 1.2
{
m_glContext = glXCreateContext( dpy, vi,
- other ? other->m_glContext : None,
+ otherGLXContext,
x11Direct );
}
}
@@ -558,18 +562,18 @@ wxGLContext::wxGLContext(wxGLCanvas *win,
XSetErrorHandler( oldHandler );
}
-wxGLContext::~wxGLContext()
+wxGLContextX11::~wxGLContextX11()
{
if ( !m_glContext )
return;
if ( m_glContext == glXGetCurrentContext() )
- ClearCurrent();
+ wxGLBackendX11_instance.ClearCurrentContext();
glXDestroyContext( wxGetX11Display(), m_glContext );
}
-bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
+bool wxGLContextX11::SetCurrent(const wxGLCanvas& win) const
{
if ( !m_glContext )
return false;
@@ -580,17 +584,11 @@ bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
return MakeCurrent(xid, m_glContext);
}
-/* static */
-void wxGLContextBase::ClearCurrent()
-{
- MakeCurrent(None, nullptr);
-}
-
// wrapper around glXMakeContextCurrent/glXMakeCurrent depending on GLX
// version
static bool MakeCurrent(GLXDrawable drawable, GLXContext context)
{
- if (wxGLCanvas::GetGLXVersion() >= 13)
+ if (wxGLBackendX11_instance.GetGLXVersion() >= 13)
return glXMakeContextCurrent( wxGetX11Display(), drawable, drawable, context);
else // GLX <= 1.2 doesn't have glXMakeContextCurrent()
return glXMakeCurrent( wxGetX11Display(), drawable, context);
@@ -610,7 +608,8 @@ static bool InitXVisualInfo(
// initialization methods and dtor
// ----------------------------------------------------------------------------
-wxGLCanvasX11::wxGLCanvasX11()
+wxGLCanvasX11::wxGLCanvasX11(wxGLCanvasUnix* canvas)
+ : wxGLCanvasUnixImpl(canvas)
{
m_fbc = nullptr;
m_vi = nullptr;
@@ -641,18 +640,19 @@ wxGLCanvasX11::~wxGLCanvasX11()
// working with GL attributes
// ----------------------------------------------------------------------------
-/* static */
-bool wxGLCanvasBase::IsExtensionSupported(const char *extension)
+bool wxGLBackendX11::IsExtensionSupported(const char *extension)
{
Display * const dpy = wxGetX11Display();
- return IsExtensionInList(glXQueryExtensionsString(dpy, DefaultScreen(dpy)),
- extension);
+ return wxGLCanvasBase::IsExtensionInList
+ (
+ glXQueryExtensionsString(dpy, DefaultScreen(dpy)),
+ extension
+ );
}
-/* static */
-bool wxGLCanvasX11::IsGLXMultiSampleAvailable()
+bool wxGLBackendX11::IsGLXMultiSampleAvailable()
{
static int s_isMultiSampleAvailable = -1;
if ( s_isMultiSampleAvailable == -1 )
@@ -675,7 +675,7 @@ static bool InitXVisualInfo(const wxGLAttributes& dispAttrs,
Display* dpy = wxGetX11Display();
- if (wxGLCanvasX11::GetGLXVersion() >= 13)
+ if (wxGLBackendX11_instance.GetGLXVersion() >= 13)
{
int returned;
*pFBC = glXChooseFBConfig(dpy, DefaultScreen(dpy), attrsListGLX, &returned);
@@ -701,8 +701,7 @@ static bool InitXVisualInfo(const wxGLAttributes& dispAttrs,
return *pXVisual != nullptr;
}
-/* static */
-bool wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs)
+bool wxGLBackendX11::IsDisplaySupported(const wxGLAttributes& dispAttrs)
{
wxX11Ptr fbc;
wxX11Ptr vi;
@@ -710,20 +709,11 @@ bool wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs)
return InitXVisualInfo(dispAttrs, fbc.Out(), vi.Out());
}
-/* static */
-bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
-{
- wxGLAttributes dispAttrs;
- ParseAttribList(attribList, dispAttrs);
-
- return IsDisplaySupported(dispAttrs);
-}
-
// ----------------------------------------------------------------------------
// default visual management
// ----------------------------------------------------------------------------
-static void FreeDefaultVisualInfo()
+void wxGLBackendX11::FreeDefaultVisualInfo()
{
if (gs_glFBCInfo)
{
@@ -737,22 +727,30 @@ static void FreeDefaultVisualInfo()
}
}
-/* static */
-bool wxGLCanvasX11::InitDefaultVisualInfo(const int *attribList)
+bool wxGLBackendX11::InitDefaultVisualInfo(const int* attribList)
{
FreeDefaultVisualInfo();
wxGLAttributes dispAttrs;
- ParseAttribList(attribList, dispAttrs);
+ wxGLCanvasBase::ParseAttribList(attribList, dispAttrs);
return InitXVisualInfo(dispAttrs, &gs_glFBCInfo, &gs_glVisualInfo);
}
+void* wxGLBackendX11::GetDefaultVisualInfo()
+{
+ return gs_glVisualInfo;
+}
+
// ----------------------------------------------------------------------------
// other GL methods
// ----------------------------------------------------------------------------
-/* static */
-int wxGLCanvasX11::GetGLXVersion()
+bool wxGLBackendX11::GetEGLVersion(int* WXUNUSED(major), int* WXUNUSED(minor))
+{
+ return false;
+}
+
+int wxGLBackendX11::GetGLXVersion()
{
static int s_glxVersion = 0;
if ( s_glxVersion == 0 )
@@ -806,7 +804,7 @@ void wxGLSetSwapInterval(Display* dpy, GLXDrawable drawable, int interval)
bool wxGLCanvasX11::SwapBuffers()
{
- const Window xid = GetXWindow();
+ const Window xid = m_canvas->GetXWindow();
wxCHECK2_MSG( xid, return false, wxT("window must be shown") );
const auto dpy = wxGetX11Display();
@@ -826,30 +824,38 @@ bool wxGLCanvasX11::SwapBuffers()
return true;
}
-bool wxGLCanvasX11::IsShownOnScreen() const
+bool wxGLCanvasX11::HasWindow() const
{
- return GetXWindow() && wxGLCanvasBase::IsShownOnScreen();
+ return m_canvas->GetXWindow();
}
// ----------------------------------------------------------------------------
-// wxGLApp
+// wxGLBackendX11
// ----------------------------------------------------------------------------
-bool wxGLApp::InitGLVisual(const int* attribList)
+/* static */
+wxGLBackend& wxGLBackendX11::Get()
{
- return wxGLCanvasX11::InitDefaultVisualInfo(attribList);
+ return wxGLBackendX11_instance;
}
-void* wxGLApp::GetXVisualInfo()
+std::unique_ptr
+wxGLBackendX11::CreateContextImpl(wxGLCanvas* win,
+ const wxGLContext* other,
+ const wxGLContextAttrs* ctxAttrs)
{
- return gs_glVisualInfo;
+ return std::make_unique(win, other, ctxAttrs);
}
-int wxGLApp::OnExit()
+std::unique_ptr
+wxGLBackendX11::CreateCanvasImpl(wxGLCanvasUnix* canvas)
{
- FreeDefaultVisualInfo();
+ return std::make_unique(canvas);
+}
- return wxGLAppBase::OnExit();
+void wxGLBackendX11::ClearCurrentContext()
+{
+ MakeCurrent(None, nullptr);
}
#endif // wxUSE_GLCANVAS