From 76de5661e45d882685b0c6b5d1d5eba0e3964e9d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 7 Dec 2025 00:49:12 +0100 Subject: [PATCH 1/7] Informally deprecate wxGLApp It is not really needed for anything and while there is no good reason to remove it (breaking code which depends on it by inheriting from this class), mention that it shouldn't be used in the new code and stop overriding GetXVisualInfo() in it when not using GTK 2, as it's the only port which actually needs it. --- include/wx/glcanvas.h | 5 +++-- include/wx/gtk/app.h | 2 ++ include/wx/unix/glegl.h | 5 ++--- include/wx/unix/glx11.h | 5 ++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/wx/glcanvas.h b/include/wx/glcanvas.h index a469b5421c..918dd20fe2 100644 --- a/include/wx/glcanvas.h +++ b/include/wx/glcanvas.h @@ -312,8 +312,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/unix/glegl.h b/include/wx/unix/glegl.h index 5155a84151..10d2f392be 100644 --- a/include/wx/unix/glegl.h +++ b/include/wx/unix/glegl.h @@ -183,13 +183,12 @@ public: 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. +#ifndef __WXGTK3__ virtual void* GetXVisualInfo() override { return wxGLCanvasEGL::GetDefaultConfig(); } +#endif // GTK < 3 // and override this wxApp method to clean up virtual int OnExit() override diff --git a/include/wx/unix/glx11.h b/include/wx/unix/glx11.h index cad490a878..61db250e43 100644 --- a/include/wx/unix/glx11.h +++ b/include/wx/unix/glx11.h @@ -115,10 +115,9 @@ class WXDLLIMPEXP_GL wxGLApp : public wxGLAppBase public: 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. +#ifndef __WXGTK3__ virtual void* GetXVisualInfo() override; +#endif // GTK < 3 // and override this wxApp method to clean up virtual int OnExit() override; From 0b574c2363f5cc4a974f369b72caaac9cec64820 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 10 Dec 2025 15:36:02 +0100 Subject: [PATCH 2/7] Add make_unique fallback implementation Define it ourselves if the standard library doesn't provide it (as is the case for the still supported g++ 4.8). --- include/wx/private/make_unique.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 include/wx/private/make_unique.h 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_ From d9df7db130ac22a6691bc4eb73ad0f691e999d7b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 10 Dec 2025 03:20:54 +0100 Subject: [PATCH 3/7] Allow choosing between GLX and EGL during run-time The same library binary can now be used to use either GLX or EGL for wxGLCanvas implementation instead of the choice being done at build time (by either always using EGL if it is enabled or always using GLX otherwise). New wxGLCanvas::PreferGLX() function (available only if wxHAS_GLX is defined) can be used to request using GLX even if EGL is available, otherwise EGL is used by default, just as before. Additionally new "opengl.egl" system option can be used to the same effect, mostly to allow users to set "wx_opengl_egl" environment variable to 0 to use GLX if possible, i.e. with X11 and not Wayland. --- Makefile.in | 29 +- build/bakefiles/files.bkl | 7 +- build/cmake/files.cmake | 7 +- build/cmake/init.cmake | 1 + build/cmake/setup.h.in | 5 +- build/files | 7 +- configure | 53 +--- configure.ac | 2 +- docs/changes.txt | 4 + docs/doxygen/mainpages/const_cpp.h | 4 + include/wx/android/setup.h | 8 - include/wx/glcanvas.h | 36 +-- include/wx/gtk/glcanvas.h | 15 +- include/wx/gtk/setup.h | 8 - include/wx/msw/setup.h | 8 - include/wx/osx/setup.h | 8 - include/wx/setup_inc.h | 8 - include/wx/univ/setup.h | 8 - include/wx/unix/{glx11.h => glcanvas.h} | 88 +++--- include/wx/unix/glegl.h | 205 ------------ include/wx/unix/private/glcanvas.h | 162 ++++++++++ include/wx/unix/private/glegl.h | 188 +++++++++++ include/wx/unix/private/glx11.h | 131 ++++++++ include/wx/x11/glcanvas.h | 6 +- interface/wx/glcanvas.h | 34 +- samples/opengl/cube/cube.cpp | 36 +++ samples/opengl/cube/cube.h | 1 + setup.h.in | 5 +- setup.h_vms | 2 - src/gtk/glcanvas.cpp | 22 +- src/unix/glcanvas.cpp | 356 +++++++++++++++++++++ src/unix/glegl.cpp | 373 ++++++++++++---------- src/unix/glx11.cpp | 398 ++++++++++++------------ 33 files changed, 1428 insertions(+), 797 deletions(-) rename include/wx/unix/{glx11.h => glcanvas.h} (58%) delete mode 100644 include/wx/unix/glegl.h create mode 100644 include/wx/unix/private/glcanvas.h create mode 100644 include/wx/unix/private/glegl.h create mode 100644 include/wx/unix/private/glx11.h create mode 100644 src/unix/glcanvas.cpp 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 918dd20fe2..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) 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/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 58% rename from include/wx/unix/glx11.h rename to include/wx/unix/glcanvas.h index 61db250e43..4f30324a03 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,35 @@ 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 + // 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 +73,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,11 +100,11 @@ private: class WXDLLIMPEXP_GL wxGLApp : public wxGLAppBase { public: + wxGLApp() = default; + virtual bool InitGLVisual(const int *attribList) override; -#ifndef __WXGTK3__ - virtual void* GetXVisualInfo() override; -#endif // GTK < 3 + virtual void* GetXVisualInfo(); // and override this wxApp method to clean up virtual int OnExit() override; @@ -126,5 +113,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 10d2f392be..0000000000 --- a/include/wx/unix/glegl.h +++ /dev/null @@ -1,205 +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); - } - -#ifndef __WXGTK3__ - virtual void* GetXVisualInfo() override - { - return wxGLCanvasEGL::GetDefaultConfig(); - } -#endif // GTK < 3 - - // 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..0ec48635b2 --- /dev/null +++ b/include/wx/unix/private/glcanvas.h @@ -0,0 +1,162 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 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..2fabb31df4 --- /dev/null +++ b/include/wx/unix/private/glegl.h @@ -0,0 +1,188 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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; + 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..cd71fe7af7 --- /dev/null +++ b/include/wx/unix/private/glx11.h @@ -0,0 +1,131 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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; + 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..14c88322a1 100644 --- a/interface/wx/glcanvas.h +++ b/interface/wx/glcanvas.h @@ -898,18 +898,6 @@ public: const wxPalette& palette = wxNullPalette); - /** - Re-creates EGLSurface. To be used after a reparent or other - changes that may invalidate the EGL drawing surface. - - Only available when wxUSE_GLCANVAS_EGL is enabled. - - @return @true if surface is successfully recreated - - @since 3.2.3 - */ - bool CreateSurface(); - /** Determines if a canvas having the specified attributes is available. This only applies for visual attributes, not rendering context attributes. @@ -945,6 +933,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..87c5c9ec9a 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,39 @@ 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 ) + { + info += "Using EGL.\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..0f4e3d9614 --- /dev/null +++ b/src/unix/glcanvas.cpp @@ -0,0 +1,356 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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 */ +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..8927d205b7 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); } @@ -837,44 +838,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 +902,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 +934,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 +950,40 @@ 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); +} + +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..74a35fefe8 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,13 +451,20 @@ 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) { + // 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()); + const int* contextAttribs = nullptr; Bool x11Direct = True; int renderType = GLX_RGBA_TYPE; @@ -483,7 +490,7 @@ wxGLContext::wxGLContext(wxGLCanvas *win, 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 +498,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 +523,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 +542,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 +565,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 +587,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 +611,8 @@ static bool InitXVisualInfo( // initialization methods and dtor // ---------------------------------------------------------------------------- -wxGLCanvasX11::wxGLCanvasX11() +wxGLCanvasX11::wxGLCanvasX11(wxGLCanvasUnix* canvas) + : wxGLCanvasUnixImpl(canvas) { m_fbc = nullptr; m_vi = nullptr; @@ -641,18 +643,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 +678,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 +704,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 +712,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 +730,25 @@ 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() +int wxGLBackendX11::GetGLXVersion() { static int s_glxVersion = 0; if ( s_glxVersion == 0 ) @@ -806,7 +802,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 +822,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 From 4817bb59b5363b9f550f03cfff391d9f8f698aea Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 10 Dec 2025 15:38:46 +0100 Subject: [PATCH 4/7] Remove redundant eglBindAPI() call Since the changes of a88a56b9fe (Fix OpenGL ES creation in EGL-based wxGLCanvas implementation, 2025-12-06) this call is not needed any more, as we'll call eglBindAPI() with the correct API to use when we know it later. --- src/unix/glegl.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/unix/glegl.cpp b/src/unix/glegl.cpp index 8927d205b7..e4e0ba8b7f 100644 --- a/src/unix/glegl.cpp +++ b/src/unix/glegl.cpp @@ -770,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 From e9647b5c1b31b141c85565241c3f549cc5198636 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 10 Dec 2025 15:42:56 +0100 Subject: [PATCH 5/7] Document wxGLCanvas::GetGLXVersion() This function has been available since more or less always and is now used in the OpenGL cube sample, so it seems like it ought to be public. --- interface/wx/glcanvas.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/interface/wx/glcanvas.h b/interface/wx/glcanvas.h index 14c88322a1..52aa92e1e8 100644 --- a/interface/wx/glcanvas.h +++ b/interface/wx/glcanvas.h @@ -898,6 +898,17 @@ public: const wxPalette& palette = wxNullPalette); + /** + 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. This only applies for visual attributes, not rendering context attributes. From 946ae2e8f2974e7e0f585a4f64235087459a5cae Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 10 Dec 2025 16:16:29 +0100 Subject: [PATCH 6/7] Add wxGLCanvas::GetEGLVersion() to wxGTK and wxX11 Provide this function if only for consistency with GetGLXVersion(). --- include/wx/unix/glcanvas.h | 7 +++++++ include/wx/unix/private/glcanvas.h | 1 + include/wx/unix/private/glegl.h | 1 + include/wx/unix/private/glx11.h | 1 + interface/wx/glcanvas.h | 22 ++++++++++++++++++++++ samples/opengl/cube/cube.cpp | 11 ++++++++++- src/unix/glcanvas.cpp | 6 ++++++ src/unix/glegl.cpp | 10 ++++++++++ src/unix/glx11.cpp | 5 +++++ 9 files changed, 63 insertions(+), 1 deletion(-) diff --git a/include/wx/unix/glcanvas.h b/include/wx/unix/glcanvas.h index 4f30324a03..437e6d2ccf 100644 --- a/include/wx/unix/glcanvas.h +++ b/include/wx/unix/glcanvas.h @@ -56,6 +56,13 @@ public: virtual bool IsShownOnScreen() const override; + // 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 // -------------------- diff --git a/include/wx/unix/private/glcanvas.h b/include/wx/unix/private/glcanvas.h index 0ec48635b2..90cfc194d3 100644 --- a/include/wx/unix/private/glcanvas.h +++ b/include/wx/unix/private/glcanvas.h @@ -107,6 +107,7 @@ public: virtual bool IsDisplaySupported(const wxGLAttributes& dispAttrs) = 0; + virtual bool GetEGLVersion(int* major, int* minor) = 0; virtual int GetGLXVersion() = 0; virtual bool IsGLXMultiSampleAvailable() = 0; diff --git a/include/wx/unix/private/glegl.h b/include/wx/unix/private/glegl.h index 2fabb31df4..705c518224 100644 --- a/include/wx/unix/private/glegl.h +++ b/include/wx/unix/private/glegl.h @@ -146,6 +146,7 @@ public: 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; diff --git a/include/wx/unix/private/glx11.h b/include/wx/unix/private/glx11.h index cd71fe7af7..4d15d898b0 100644 --- a/include/wx/unix/private/glx11.h +++ b/include/wx/unix/private/glx11.h @@ -89,6 +89,7 @@ public: 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; diff --git a/interface/wx/glcanvas.h b/interface/wx/glcanvas.h index 52aa92e1e8..d69c712ae7 100644 --- a/interface/wx/glcanvas.h +++ b/interface/wx/glcanvas.h @@ -898,6 +898,28 @@ public: const wxPalette& palette = wxNullPalette); + /** + Return the version of EGL being used or @false if not using EGL. + + 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. + + @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.3.2 + */ + static bool GetEGLVersion(int* major, int* minor); + /** Return the version of GLX being used or 0 if not using GLX. diff --git a/samples/opengl/cube/cube.cpp b/samples/opengl/cube/cube.cpp index 87c5c9ec9a..dbaaade98e 100644 --- a/samples/opengl/cube/cube.cpp +++ b/samples/opengl/cube/cube.cpp @@ -503,7 +503,16 @@ void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) const int glxVersion = wxGLCanvasUnix::GetGLXVersion(); if ( glxVersion == 0 ) { - info += "Using EGL.\n\n"; + 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 { diff --git a/src/unix/glcanvas.cpp b/src/unix/glcanvas.cpp index 0f4e3d9614..4afc7046b2 100644 --- a/src/unix/glcanvas.cpp +++ b/src/unix/glcanvas.cpp @@ -301,6 +301,12 @@ void wxGLCanvasUnix::PreferGLX() #endif // wxHAS_EGL } +/* static */ +bool wxGLCanvasUnix::GetEGLVersion(int* major, int* minor) +{ + return wxGLBackend::Get().GetEGLVersion(major, minor); +} + /* static */ int wxGLCanvasUnix::GetGLXVersion() { diff --git a/src/unix/glegl.cpp b/src/unix/glegl.cpp index e4e0ba8b7f..e9b7709930 100644 --- a/src/unix/glegl.cpp +++ b/src/unix/glegl.cpp @@ -969,6 +969,16 @@ 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. diff --git a/src/unix/glx11.cpp b/src/unix/glx11.cpp index 74a35fefe8..4769f05562 100644 --- a/src/unix/glx11.cpp +++ b/src/unix/glx11.cpp @@ -748,6 +748,11 @@ void* wxGLBackendX11::GetDefaultVisualInfo() // other GL methods // ---------------------------------------------------------------------------- +bool wxGLBackendX11::GetEGLVersion(int* WXUNUSED(major), int* WXUNUSED(minor)) +{ + return false; +} + int wxGLBackendX11::GetGLXVersion() { static int s_glxVersion = 0; From 242dacdb9f3b47a1e7c1f2f0f622e6cc5853d95f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 10 Dec 2025 16:13:13 +0100 Subject: [PATCH 7/7] Make wxGLContextX11 ctor code a bit shorter and more clear It wasn't obvious why did we duplicate identical code for attributes initialization before, so stop duplicating it and write a comment explaining what's going on here and why we can't just initialize the various variables from the provided or fallback attributes directly. No real changes. --- src/unix/glx11.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/unix/glx11.cpp b/src/unix/glx11.cpp index 4769f05562..2b70aacba0 100644 --- a/src/unix/glx11.cpp +++ b/src/unix/glx11.cpp @@ -465,27 +465,24 @@ wxGLContextX11::wxGLContextX11(wxGLCanvas *win, // The window must also be of the appropriate type. auto const winX11 = static_cast(win->GetImpl()); - const int* contextAttribs = nullptr; + // 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;