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