From 8924b77da4c01a8b57ceecbf020574422ad7debe Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 19 May 2020 22:33:48 +0200 Subject: [PATCH] egldisplay: Backport changes for creating headless EGL contexts Backport of fbc49474557fe7b2ec1875ebb1cfb62e96e7f103 and 9f1289b4920074feb7f0b9b203d2a5b6e811c816 See #557 --- makepanda/makepanda.py | 32 ++++- panda/metalibs/pandagl/pandagl.cxx | 19 ++- panda/src/egldisplay/config_egldisplay.cxx | 10 +- panda/src/egldisplay/config_egldisplay.h | 10 +- panda/src/egldisplay/eglGraphicsBuffer.cxx | 8 +- panda/src/egldisplay/eglGraphicsPipe.I | 8 ++ panda/src/egldisplay/eglGraphicsPipe.cxx | 47 ++++++- panda/src/egldisplay/eglGraphicsPipe.h | 30 +++-- panda/src/egldisplay/eglGraphicsPixmap.cxx | 13 +- panda/src/egldisplay/eglGraphicsPixmap.h | 4 + .../egldisplay/eglGraphicsStateGuardian.cxx | 118 +++++++++--------- .../src/egldisplay/eglGraphicsStateGuardian.h | 39 +++--- panda/src/egldisplay/eglGraphicsWindow.cxx | 11 +- panda/src/egldisplay/eglGraphicsWindow.h | 4 + 14 files changed, 240 insertions(+), 113 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 88735bc34a..e8391482ff 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -2695,6 +2695,9 @@ def WriteConfigSettings(): dtool_config["PHAVE_LINUX_INPUT_H"] = 'UNDEF' dtool_config["IS_OSX"] = '1' + if PkgSkip("X11"): + dtool_config["HAVE_GLX"] = 'UNDEF' + if (GetTarget() == "freebsd"): dtool_config["IS_LINUX"] = 'UNDEF' dtool_config["HAVE_VIDEO4LINUX"] = 'UNDEF' @@ -5141,13 +5144,33 @@ if (GetTarget() == 'windows' and PkgSkip("GL")==0 and not RUNTIME): # DIRECTORY: panda/src/egldisplay/ # -if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0 and not RUNTIME): +# If we're not compiling with any windowing system at all, but we do have EGL, +# we can use that to create a headless libpandagl instead. +if not PkgSkip("EGL") and not PkgSkip("GL") and PkgSkip("X11") and GetTarget() not in ('windows', 'darwin') and not RUNTIME: + DefSymbol('EGL', 'HAVE_EGL', '') + OPTS=['DIR:panda/src/egldisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGL', 'GL', 'EGL'] + TargetAdd('pandagl_egldisplay_composite1.obj', opts=OPTS, input='p3egldisplay_composite1.cxx') + OPTS=['DIR:panda/metalibs/pandagl', 'BUILDING:PANDAGL', 'GL', 'EGL'] + TargetAdd('pandagl_pandagl.obj', opts=OPTS, input='pandagl.cxx') + TargetAdd('libpandagl.dll', input='pandagl_pandagl.obj') + TargetAdd('libpandagl.dll', input='p3glgsg_config_glgsg.obj') + TargetAdd('libpandagl.dll', input='p3glgsg_glgsg.obj') + TargetAdd('libpandagl.dll', input='pandagl_egldisplay_composite1.obj') + TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS) + TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'EGL', 'CGGL']) + +# +# DIRECTORY: panda/src/egldisplay/ +# + +if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and not RUNTIME): DefSymbol('GLES', 'OPENGLES_1', '') OPTS=['DIR:panda/src/egldisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGLES', 'GLES', 'EGL'] TargetAdd('pandagles_egldisplay_composite1.obj', opts=OPTS, input='p3egldisplay_composite1.cxx') OPTS=['DIR:panda/metalibs/pandagles', 'BUILDING:PANDAGLES', 'GLES', 'EGL'] TargetAdd('pandagles_pandagles.obj', opts=OPTS, input='pandagles.cxx') - TargetAdd('libpandagles.dll', input='p3x11display_composite1.obj') + if not PkgSkip("X11"): + TargetAdd('libpandagles.dll', input='p3x11display_composite1.obj') TargetAdd('libpandagles.dll', input='pandagles_pandagles.obj') TargetAdd('libpandagles.dll', input='p3glesgsg_config_glesgsg.obj') TargetAdd('libpandagles.dll', input='p3glesgsg_glesgsg.obj') @@ -5159,13 +5182,14 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0 and not RUNTI # DIRECTORY: panda/src/egldisplay/ # -if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0 and PkgSkip("X11")==0 and not RUNTIME): +if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0 and not RUNTIME): DefSymbol('GLES2', 'OPENGLES_2', '') OPTS=['DIR:panda/src/egldisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGLES2', 'GLES2', 'EGL'] TargetAdd('pandagles2_egldisplay_composite1.obj', opts=OPTS, input='p3egldisplay_composite1.cxx') OPTS=['DIR:panda/metalibs/pandagles2', 'BUILDING:PANDAGLES2', 'GLES2', 'EGL'] TargetAdd('pandagles2_pandagles2.obj', opts=OPTS, input='pandagles2.cxx') - TargetAdd('libpandagles2.dll', input='p3x11display_composite1.obj') + if not PkgSkip("X11"): + TargetAdd('libpandagles2.dll', input='p3x11display_composite1.obj') TargetAdd('libpandagles2.dll', input='pandagles2_pandagles2.obj') TargetAdd('libpandagles2.dll', input='p3gles2gsg_config_gles2gsg.obj') TargetAdd('libpandagles2.dll', input='p3gles2gsg_gles2gsg.obj') diff --git a/panda/metalibs/pandagl/pandagl.cxx b/panda/metalibs/pandagl/pandagl.cxx index 0e33961c9f..e6f01d9ce2 100644 --- a/panda/metalibs/pandagl/pandagl.cxx +++ b/panda/metalibs/pandagl/pandagl.cxx @@ -26,8 +26,13 @@ #include "glxGraphicsPipe.h" #endif -#if !defined(HAVE_WGL) && !defined(HAVE_COCOA) && !defined(HAVE_CARBON) && !defined(HAVE_GLX) -#error One of HAVE_WGL, HAVE_COCOA, HAVE_CARBON or HAVE_GLX must be defined when compiling pandagl! +#if defined(HAVE_EGL) && !defined(HAVE_X11) +#include "config_egldisplay.h" +#include "eglGraphicsPipe.h" +#endif + +#if !defined(HAVE_WGL) && !defined(HAVE_COCOA) && !defined(HAVE_CARBON) && !defined(HAVE_GLX) && !defined(HAVE_EGL) +#error One of HAVE_WGL, HAVE_COCOA, HAVE_CARBON, HAVE_GLX or HAVE_EGL must be defined when compiling pandagl! #endif /** @@ -50,9 +55,13 @@ init_libpandagl() { init_libosxdisplay(); #endif -#ifdef IS_LINUX +#ifdef HAVE_GLX init_libglxdisplay(); #endif + +#if defined(HAVE_EGL) && !defined(HAVE_X11) + init_libegldisplay(); +#endif } /** @@ -75,5 +84,9 @@ get_pipe_type_pandagl() { return glxGraphicsPipe::get_class_type().get_index(); #endif +#if defined(HAVE_EGL) && !defined(HAVE_X11) + return eglGraphicsPipe::get_class_type().get_index(); +#endif + return 0; } diff --git a/panda/src/egldisplay/config_egldisplay.cxx b/panda/src/egldisplay/config_egldisplay.cxx index bb5b623a47..e80137290d 100644 --- a/panda/src/egldisplay/config_egldisplay.cxx +++ b/panda/src/egldisplay/config_egldisplay.cxx @@ -21,8 +21,8 @@ #include "dconfig.h" #include "pandaSystem.h" -#if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_PANDAGLES) && !defined(BUILDING_PANDAGLES2) - #error Buildsystem error: BUILDING_PANDAGLES(2) not defined +#if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_PANDAGLES) && !defined(BUILDING_PANDAGLES2) && !defined(BUILDING_PANDAGL) + #error Buildsystem error: BUILDING_PANDAGL(ES(2)) not defined #endif Configure(config_egldisplay); @@ -48,8 +48,10 @@ init_libegldisplay() { eglGraphicsBuffer::init_type(); eglGraphicsPipe::init_type(); +#ifdef HAVE_X11 eglGraphicsPixmap::init_type(); eglGraphicsWindow::init_type(); +#endif eglGraphicsStateGuardian::init_type(); GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr(); @@ -59,8 +61,10 @@ init_libegldisplay() { PandaSystem *ps = PandaSystem::get_global_ptr(); #ifdef OPENGLES_2 ps->set_system_tag("OpenGL ES 2", "window_system", "EGL"); -#else +#elif defined(OPENGLES_1) ps->set_system_tag("OpenGL ES", "window_system", "EGL"); +#else + ps->set_system_tag("OpenGL", "window_system", "EGL"); #endif } diff --git a/panda/src/egldisplay/config_egldisplay.h b/panda/src/egldisplay/config_egldisplay.h index 40e30893b8..a85df9748e 100644 --- a/panda/src/egldisplay/config_egldisplay.h +++ b/panda/src/egldisplay/config_egldisplay.h @@ -23,20 +23,22 @@ #if defined(OPENGLES_1) && defined(OPENGLES_2) #error OPENGLES_1 and OPENGLES_2 cannot be defined at the same time! #endif -#if !defined(OPENGLES_1) && !defined(OPENGLES_2) - #error Either OPENGLES_1 or OPENGLES_2 must be defined when compiling egldisplay! -#endif #ifdef OPENGLES_2 NotifyCategoryDecl(egldisplay, EXPCL_PANDAGLES2, EXPTP_PANDAGLES2); extern EXPCL_PANDAGLES2 void init_libegldisplay(); extern EXPCL_PANDAGLES2 const std::string get_egl_error_string(int error); -#else +#elif defined(OPENGLES_1) NotifyCategoryDecl(egldisplay, EXPCL_PANDAGLES, EXPTP_PANDAGLES); extern EXPCL_PANDAGLES void init_libegldisplay(); extern EXPCL_PANDAGLES const std::string get_egl_error_string(int error); +#else + NotifyCategoryDecl(egldisplay, EXPCL_PANDAGL, EXPTP_PANDAGL); + + extern EXPCL_PANDAGL void init_libegldisplay(); + extern EXPCL_PANDAGL const std::string get_egl_error_string(int error); #endif #endif diff --git a/panda/src/egldisplay/eglGraphicsBuffer.cxx b/panda/src/egldisplay/eglGraphicsBuffer.cxx index 7319f25430..2cfbff83b4 100644 --- a/panda/src/egldisplay/eglGraphicsBuffer.cxx +++ b/panda/src/egldisplay/eglGraphicsBuffer.cxx @@ -127,7 +127,7 @@ close_buffer() { if (_gsg != nullptr) { eglGraphicsStateGuardian *eglgsg; DCAST_INTO_V(eglgsg, _gsg); - if (!eglMakeCurrent(eglgsg->_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) { + if (!eglMakeCurrent(_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) { egldisplay_cat.error() << "Failed to call eglMakeCurrent: " << get_egl_error_string(eglGetError()) << "\n"; } @@ -159,7 +159,7 @@ open_buffer() { if (_gsg == 0) { // There is no old gsg. Create a new one. eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr); - eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), true, false); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, true, false); _gsg = eglgsg; } else { // If the old gsg has the wrong pixel format, create a new one that shares @@ -167,7 +167,7 @@ open_buffer() { DCAST_INTO_R(eglgsg, _gsg, false); if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) { eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg); - eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), true, false); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, true, false); _gsg = eglgsg; } } @@ -178,6 +178,8 @@ open_buffer() { return false; } + _egl_display = eglgsg->_egl_display; + int attrib_list[] = { EGL_WIDTH, _size.get_x(), EGL_HEIGHT, _size.get_y(), diff --git a/panda/src/egldisplay/eglGraphicsPipe.I b/panda/src/egldisplay/eglGraphicsPipe.I index 53d9c311af..216c0ad721 100644 --- a/panda/src/egldisplay/eglGraphicsPipe.I +++ b/panda/src/egldisplay/eglGraphicsPipe.I @@ -10,3 +10,11 @@ * @author rdb * @date 2009-05-21 */ + +/** + * + */ +INLINE EGLDisplay eglGraphicsPipe:: +get_egl_display() const { + return _egl_display; +} diff --git a/panda/src/egldisplay/eglGraphicsPipe.cxx b/panda/src/egldisplay/eglGraphicsPipe.cxx index 17594f799e..18c2317664 100644 --- a/panda/src/egldisplay/eglGraphicsPipe.cxx +++ b/panda/src/egldisplay/eglGraphicsPipe.cxx @@ -25,19 +25,39 @@ TypeHandle eglGraphicsPipe::_type_handle; * */ eglGraphicsPipe:: -eglGraphicsPipe(const std::string &display) : x11GraphicsPipe(display) { +eglGraphicsPipe() { + //NB. if the X11 display failed to open, _display will be 0, which is a valid + // input to eglGetDisplay - it means to open the default display. +#ifdef HAVE_X11 _egl_display = eglGetDisplay((NativeDisplayType) _display); +#else + _egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); +#endif if (!eglInitialize(_egl_display, nullptr, nullptr)) { egldisplay_cat.error() << "Couldn't initialize the EGL display: " << get_egl_error_string(eglGetError()) << "\n"; + _is_valid = false; + return; } +#if defined(OPENGLES_1) || defined(OPENGLES_2) if (!eglBindAPI(EGL_OPENGL_ES_API)) { egldisplay_cat.error() << "Couldn't bind EGL to the OpenGL ES API: " << get_egl_error_string(eglGetError()) << "\n"; +#else + if (!eglBindAPI(EGL_OPENGL_API)) { + egldisplay_cat.error() + << "Couldn't bind EGL to the OpenGL API: " + << get_egl_error_string(eglGetError()) << "\n"; +#endif + _is_valid = false; + return; } + + // Even if we don't have an X11 display, we can still render headless. + _is_valid = true; } /** @@ -61,7 +81,11 @@ eglGraphicsPipe:: */ std::string eglGraphicsPipe:: get_interface_name() const { +#if defined(OPENGLES_1) || defined(OPENGLES_2) return "OpenGL ES"; +#else + return "OpenGL"; +#endif } /** @@ -110,6 +134,10 @@ make_output(const std::string &name, // First thing to try: an eglGraphicsWindow if (retry == 0) { +#ifdef HAVE_X11 + if (!_display) { + return nullptr; + } if (((flags&BF_require_parasite)!=0)|| ((flags&BF_refuse_window)!=0)|| ((flags&BF_resizeable)!=0)|| @@ -121,9 +149,12 @@ make_output(const std::string &name, } return new eglGraphicsWindow(engine, this, name, fb_prop, win_prop, flags, gsg, host); +#else + return nullptr; +#endif } - // Second thing to try: a GLES(2)GraphicsBuffer + // Second thing to try: a GL(ES(2))GraphicsBuffer if (retry == 1) { if ((host==0)|| // (!gl_support_fbo)|| @@ -154,9 +185,12 @@ make_output(const std::string &name, #ifdef OPENGLES_2 return new GLES2GraphicsBuffer(engine, this, name, fb_prop, win_prop, flags, gsg, host); -#else +#elif defined(OPENGLES_1) return new GLESGraphicsBuffer(engine, this, name, fb_prop, win_prop, flags, gsg, host); +#else + return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop, + flags, gsg, host); #endif } @@ -184,6 +218,10 @@ make_output(const std::string &name, // Fourth thing to try: an eglGraphicsPixmap. if (retry == 3) { +#ifdef HAVE_X11 + if (!_display) { + return nullptr; + } if (((flags&BF_require_parasite)!=0)|| ((flags&BF_require_window)!=0)|| ((flags&BF_resizeable)!=0)|| @@ -198,6 +236,9 @@ make_output(const std::string &name, return new eglGraphicsPixmap(engine, this, name, fb_prop, win_prop, flags, gsg, host); +#else + return nullptr; +#endif } // Nothing else left to try. diff --git a/panda/src/egldisplay/eglGraphicsPipe.h b/panda/src/egldisplay/eglGraphicsPipe.h index aebd9c70e1..def344a61c 100644 --- a/panda/src/egldisplay/eglGraphicsPipe.h +++ b/panda/src/egldisplay/eglGraphicsPipe.h @@ -15,7 +15,14 @@ #define EGLGRAPHICSPIPE_H #include "pandabase.h" + +#ifdef HAVE_X11 #include "x11GraphicsPipe.h" +typedef x11GraphicsPipe BaseGraphicsPipe; +#else +#include "graphicsPipe.h" +typedef GraphicsPipe BaseGraphicsPipe; +#endif #ifdef OPENGLES_2 #include "gles2gsg.h" @@ -25,11 +32,16 @@ #define NativeDisplayType EGLNativeDisplayType #define NativePixmapType EGLNativePixmapType #define NativeWindowType EGLNativeWindowType -#else +#elif defined(OPENGLES_1) #include "glesgsg.h" #include "pre_x11_include.h" #include #include "post_x11_include.h" +#else + #include "glgsg.h" + #include "pre_x11_include.h" + #include + #include "post_x11_include.h" #endif class FrameBufferProperties; @@ -42,14 +54,16 @@ class eglGraphicsWindow; * This graphics pipe represents the interface for creating OpenGL ES graphics * windows on an X-based (e.g. Unix) client. */ -class eglGraphicsPipe : public x11GraphicsPipe { +class eglGraphicsPipe : public BaseGraphicsPipe { public: - eglGraphicsPipe(const std::string &display = std::string()); + eglGraphicsPipe(); virtual ~eglGraphicsPipe(); virtual std::string get_interface_name() const; static PT(GraphicsPipe) pipe_constructor(); + INLINE EGLDisplay get_egl_display() const; + protected: virtual PT(GraphicsOutput) make_output(const std::string &name, const FrameBufferProperties &fb_prop, @@ -62,16 +76,16 @@ protected: bool &precertify); private: - EGLDisplay _egl_display; + EGLDisplay _egl_display = 0; public: static TypeHandle get_class_type() { return _type_handle; } static void init_type() { - x11GraphicsPipe::init_type(); + BaseGraphicsPipe::init_type(); register_type(_type_handle, "eglGraphicsPipe", - x11GraphicsPipe::get_class_type()); + BaseGraphicsPipe::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); @@ -80,10 +94,6 @@ public: private: static TypeHandle _type_handle; - - friend class eglGraphicsBuffer; - friend class eglGraphicsPixmap; - friend class eglGraphicsWindow; }; #include "eglGraphicsPipe.I" diff --git a/panda/src/egldisplay/eglGraphicsPixmap.cxx b/panda/src/egldisplay/eglGraphicsPixmap.cxx index 5933416f5c..946499746c 100644 --- a/panda/src/egldisplay/eglGraphicsPixmap.cxx +++ b/panda/src/egldisplay/eglGraphicsPixmap.cxx @@ -12,6 +12,9 @@ */ #include "eglGraphicsPixmap.h" + +#ifdef HAVE_X11 + #include "eglGraphicsWindow.h" #include "eglGraphicsStateGuardian.h" #include "config_egldisplay.h" @@ -37,8 +40,7 @@ eglGraphicsPixmap(GraphicsEngine *engine, GraphicsPipe *pipe, { eglGraphicsPipe *egl_pipe; DCAST_INTO_V(egl_pipe, _pipe); - _display = egl_pipe->get_display(); - _egl_display = egl_pipe->_egl_display; + _egl_display = egl_pipe->get_egl_display(); _drawable = None; _x_pixmap = None; _egl_surface = EGL_NO_SURFACE; @@ -167,7 +169,7 @@ open_buffer() { if (_gsg == 0) { // There is no old gsg. Create a new one. eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr); - eglgsg->choose_pixel_format(_fb_properties, _display, egl_pipe->get_screen(), false, true); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, false, true); _gsg = eglgsg; } else { // If the old gsg has the wrong pixel format, create a new one that shares @@ -175,7 +177,7 @@ open_buffer() { DCAST_INTO_R(eglgsg, _gsg, false); if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) { eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg); - eglgsg->choose_pixel_format(_fb_properties, _display, egl_pipe->get_screen(), false, true); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, false, true); _gsg = eglgsg; } } @@ -194,6 +196,7 @@ open_buffer() { return false; } + _display = egl_pipe->get_display(); _drawable = egl_pipe->get_root(); if (_host != nullptr) { if (_host->is_of_type(eglGraphicsWindow::get_class_type())) { @@ -241,3 +244,5 @@ open_buffer() { _is_valid = true; return true; } + +#endif // HAVE_X11 diff --git a/panda/src/egldisplay/eglGraphicsPixmap.h b/panda/src/egldisplay/eglGraphicsPixmap.h index ed7e7f90e9..95cb7842c0 100644 --- a/panda/src/egldisplay/eglGraphicsPixmap.h +++ b/panda/src/egldisplay/eglGraphicsPixmap.h @@ -16,6 +16,8 @@ #include "pandabase.h" +#ifdef HAVE_X11 + #include "eglGraphicsPipe.h" #include "graphicsBuffer.h" @@ -67,4 +69,6 @@ private: static TypeHandle _type_handle; }; +#endif // HAVE_X11 + #endif diff --git a/panda/src/egldisplay/eglGraphicsStateGuardian.cxx b/panda/src/egldisplay/eglGraphicsStateGuardian.cxx index ae3867feec..26f55f3b74 100644 --- a/panda/src/egldisplay/eglGraphicsStateGuardian.cxx +++ b/panda/src/egldisplay/eglGraphicsStateGuardian.cxx @@ -25,19 +25,11 @@ TypeHandle eglGraphicsStateGuardian::_type_handle; eglGraphicsStateGuardian:: eglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe, eglGraphicsStateGuardian *share_with) : -#ifdef OPENGLES_2 - GLES2GraphicsStateGuardian(engine, pipe) -#else - GLESGraphicsStateGuardian(engine, pipe) -#endif + BaseGraphicsStateGuardian(engine, pipe) { _share_context=0; _context=0; - _display=0; _egl_display=0; - _screen=0; - _visual=0; - _visuals=0; _fbconfig=0; if (share_with != nullptr) { @@ -51,9 +43,6 @@ eglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe, */ eglGraphicsStateGuardian:: ~eglGraphicsStateGuardian() { - if (_visuals != nullptr) { - XFree(_visuals); - } if (_context != (EGLContext)nullptr) { if (!eglDestroyContext(_egl_display, _context)) { egldisplay_cat.error() << "Failed to destroy EGL context: " @@ -108,11 +97,6 @@ get_properties(FrameBufferProperties &properties, slow = true; } - if ((surface_type & EGL_WINDOW_BIT)==0) { - // We insist on having a context that will support an onscreen window. - return; - } - properties.set_back_buffers(1); properties.set_rgb_color(1); properties.set_rgba_bits(red_size, green_size, blue_size, alpha_size); @@ -131,26 +115,23 @@ get_properties(FrameBufferProperties &properties, */ void eglGraphicsStateGuardian:: choose_pixel_format(const FrameBufferProperties &properties, - X11_Display *display, - int screen, bool need_pbuffer, bool need_pixmap) { + eglGraphicsPipe *egl_pipe, bool need_window, + bool need_pbuffer, bool need_pixmap) { - _display = display; - _egl_display = eglGetDisplay((NativeDisplayType) display); - _screen = screen; + _egl_display = egl_pipe->get_egl_display(); _context = 0; _fbconfig = 0; - _visual = 0; - _visuals = 0; _fbprops.clear(); int attrib_list[] = { -#ifdef OPENGLES_1 +#if defined(OPENGLES_1) EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, -#endif -#ifdef OPENGLES_2 +#elif defined(OPENGLES_2) EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#else + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, #endif - EGL_SURFACE_TYPE, EGL_DONT_CARE, + EGL_SURFACE_TYPE, need_window ? EGL_WINDOW_BIT : EGL_DONT_CARE, EGL_NONE }; @@ -206,23 +187,56 @@ choose_pixel_format(const FrameBufferProperties &properties, best_props = fbprops; } } - int depth = DefaultDepth(_display, _screen); - _visual = new XVisualInfo; - XMatchVisualInfo(_display, _screen, depth, TrueColor, _visual); +#ifdef HAVE_X11 + X11_Display *display = egl_pipe->get_display(); + if (display) { + int screen = egl_pipe->get_screen(); + int depth = DefaultDepth(display, screen); + _visual = new XVisualInfo; + XMatchVisualInfo(display, screen, depth, TrueColor, _visual); + } +#endif if (best_quality > 0) { egldisplay_cat.debug() << "Chosen config " << best_result << ": " << best_props << "\n"; _fbconfig = configs[best_result]; + + EGLint attribs[32]; + int n = 0; + #ifdef OPENGLES_2 - EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; - _context = eglCreateContext(_egl_display, _fbconfig, _share_context, context_attribs); -#else - _context = eglCreateContext(_egl_display, _fbconfig, _share_context, nullptr); + attribs[n++] = EGL_CONTEXT_CLIENT_VERSION; + attribs[n++] = 2; +#elif defined(OPENGLES_1) +#else // Regular OpenGL + if (gl_version.get_num_words() > 0) { + attribs[n++] = EGL_CONTEXT_MAJOR_VERSION; + attribs[n++] = gl_version[0]; + if (gl_version.get_num_words() > 1) { + attribs[n++] = EGL_CONTEXT_MINOR_VERSION; + attribs[n++] = gl_version[1]; + } + } + if (gl_debug) { + attribs[n++] = EGL_CONTEXT_OPENGL_DEBUG; + attribs[n++] = EGL_TRUE; + } + if (gl_forward_compatible) { + attribs[n++] = EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE; + attribs[n++] = EGL_TRUE; + } #endif + attribs[n] = EGL_NONE; + + _context = eglCreateContext(_egl_display, _fbconfig, _share_context, (n > 0) ? attribs : nullptr); + int err = eglGetError(); if (_context && err == EGL_SUCCESS) { - if (_visual) { +#ifdef HAVE_X11 + if (!display || _visual) +#endif + { // This is set during window creation, but for now we have to pretend // that we can honor the request, if we support the extension. if (properties.get_srgb_color()) { @@ -248,8 +262,9 @@ choose_pixel_format(const FrameBufferProperties &properties, << get_egl_error_string(err) << "\n"; _fbconfig = 0; _context = 0; +#ifdef HAVE_X11 _visual = 0; - _visuals = 0; +#endif } egldisplay_cat.error() << @@ -263,11 +278,7 @@ choose_pixel_format(const FrameBufferProperties &properties, */ void eglGraphicsStateGuardian:: reset() { -#ifdef OPENGLES_2 - GLES2GraphicsStateGuardian::reset(); -#else - GLESGraphicsStateGuardian::reset(); -#endif + BaseGraphicsStateGuardian::reset(); if (_gl_renderer == "Software Rasterizer") { _fbprops.set_force_software(1); @@ -295,13 +306,11 @@ egl_is_at_least_version(int major_version, int minor_version) const { */ void eglGraphicsStateGuardian:: gl_flush() const { +#ifdef HAVE_X11 // This call requires synchronization with X. LightReMutexHolder holder(eglGraphicsPipe::_x_mutex); -#ifdef OPENGLES_2 - GLES2GraphicsStateGuardian::gl_flush(); -#else - GLESGraphicsStateGuardian::gl_flush(); #endif + BaseGraphicsStateGuardian::gl_flush(); } /** @@ -309,13 +318,11 @@ gl_flush() const { */ GLenum eglGraphicsStateGuardian:: gl_get_error() const { +#ifdef HAVE_X11 // This call requires synchronization with X. LightReMutexHolder holder(eglGraphicsPipe::_x_mutex); -#ifdef OPENGLES_2 - return GLES2GraphicsStateGuardian::gl_get_error(); -#else - return GLESGraphicsStateGuardian::gl_get_error(); #endif + return BaseGraphicsStateGuardian::gl_get_error(); } /** @@ -323,11 +330,7 @@ gl_get_error() const { */ void eglGraphicsStateGuardian:: query_gl_version() { -#ifdef OPENGLES_2 - GLES2GraphicsStateGuardian::query_gl_version(); -#else - GLESGraphicsStateGuardian::query_gl_version(); -#endif + BaseGraphicsStateGuardian::query_gl_version(); // Calling eglInitialize on an already-initialized display will just provide // us the version numbers. @@ -342,9 +345,12 @@ query_gl_version() { #ifdef OPENGLES_2 if (gles2gsg_cat.is_debug()) { gles2gsg_cat.debug() -#else +#elif defined(OPENGLES_1) if (glesgsg_cat.is_debug()) { glesgsg_cat.debug() +#else + if (glgsg_cat.is_debug()) { + glgsg_cat.debug() #endif << "EGL_VERSION = " << _egl_version_major << "." << _egl_version_minor << "\n"; diff --git a/panda/src/egldisplay/eglGraphicsStateGuardian.h b/panda/src/egldisplay/eglGraphicsStateGuardian.h index ab47d7adf1..608e9aa080 100644 --- a/panda/src/egldisplay/eglGraphicsStateGuardian.h +++ b/panda/src/egldisplay/eglGraphicsStateGuardian.h @@ -16,26 +16,32 @@ #include "pandabase.h" #include "eglGraphicsPipe.h" + +#ifdef HAVE_X11 #include "get_x11.h" +#endif + +#ifdef OPENGLES_2 +typedef GLES2GraphicsStateGuardian BaseGraphicsStateGuardian; +#elif defined(OPENGLES_1) +typedef GLESGraphicsStateGuardian BaseGraphicsStateGuardian; +#else +typedef GLGraphicsStateGuardian BaseGraphicsStateGuardian; +#endif /** * A tiny specialization on GLESGraphicsStateGuardian to add some egl-specific * information. */ -#ifdef OPENGLES_2 -class eglGraphicsStateGuardian : public GLES2GraphicsStateGuardian { -#else -class eglGraphicsStateGuardian : public GLESGraphicsStateGuardian { -#endif +class eglGraphicsStateGuardian : public BaseGraphicsStateGuardian { public: INLINE const FrameBufferProperties &get_fb_properties() const; void get_properties(FrameBufferProperties &properties, bool &pbuffer_supported, bool &pixmap_supported, bool &slow, EGLConfig config); void choose_pixel_format(const FrameBufferProperties &properties, - X11_Display *_display, - int _screen, - bool need_pbuffer, bool need_pixmap); + eglGraphicsPipe *egl_pipe, bool need_window, + bool need_pbuffer, bool need_pixmap); eglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe, eglGraphicsStateGuardian *share_with); @@ -49,10 +55,9 @@ public: EGLContext _share_context; EGLContext _context; EGLDisplay _egl_display; - X11_Display *_display; - int _screen; - XVisualInfo *_visual; - XVisualInfo *_visuals; +#ifdef HAVE_X11 + XVisualInfo *_visual = nullptr; +#endif EGLConfig _fbconfig; FrameBufferProperties _fbprops; @@ -72,15 +77,9 @@ public: return _type_handle; } static void init_type() { -#ifdef OPENGLES_2 - GLES2GraphicsStateGuardian::init_type(); + BaseGraphicsStateGuardian::init_type(); register_type(_type_handle, "eglGraphicsStateGuardian", - GLES2GraphicsStateGuardian::get_class_type()); -#else - GLESGraphicsStateGuardian::init_type(); - register_type(_type_handle, "eglGraphicsStateGuardian", - GLESGraphicsStateGuardian::get_class_type()); -#endif + BaseGraphicsStateGuardian::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/egldisplay/eglGraphicsWindow.cxx b/panda/src/egldisplay/eglGraphicsWindow.cxx index 8827325ce0..c85ff9d8df 100644 --- a/panda/src/egldisplay/eglGraphicsWindow.cxx +++ b/panda/src/egldisplay/eglGraphicsWindow.cxx @@ -12,6 +12,9 @@ */ #include "eglGraphicsWindow.h" + +#ifdef HAVE_X11 + #include "eglGraphicsStateGuardian.h" #include "config_egldisplay.h" #include "eglGraphicsPipe.h" @@ -52,7 +55,7 @@ eglGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, { eglGraphicsPipe *egl_pipe; DCAST_INTO_V(egl_pipe, _pipe); - _egl_display = egl_pipe->_egl_display; + _egl_display = egl_pipe->get_egl_display(); _egl_surface = 0; } @@ -214,7 +217,7 @@ open_window() { if (_gsg == 0) { // There is no old gsg. Create a new one. eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr); - eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), false, false); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, true, false, false); _gsg = eglgsg; } else { // If the old gsg has the wrong pixel format, create a new one that shares @@ -222,7 +225,7 @@ open_window() { DCAST_INTO_R(eglgsg, _gsg, false); if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) { eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg); - eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), false, false); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, true, false, false); _gsg = eglgsg; } } @@ -275,3 +278,5 @@ open_window() { return true; } + +#endif // HAVE_X11 diff --git a/panda/src/egldisplay/eglGraphicsWindow.h b/panda/src/egldisplay/eglGraphicsWindow.h index 3d4ef62e44..1c359aa666 100644 --- a/panda/src/egldisplay/eglGraphicsWindow.h +++ b/panda/src/egldisplay/eglGraphicsWindow.h @@ -16,6 +16,8 @@ #include "pandabase.h" +#ifdef HAVE_X11 + #include "eglGraphicsPipe.h" #include "x11GraphicsWindow.h" @@ -65,4 +67,6 @@ private: #include "eglGraphicsWindow.I" +#endif // HAVE_X11 + #endif