diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index b34cecd011..27d5668abb 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -4494,13 +4494,14 @@ if (GetTarget() == 'windows' and PkgSkip("GL")==0): # DIRECTORY: panda/src/egldisplay/ # -if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0): +if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0): 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') @@ -4512,13 +4513,14 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0): # DIRECTORY: panda/src/egldisplay/ # -if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0 and PkgSkip("X11")==0): +if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0): 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/src/egldisplay/config_egldisplay.cxx b/panda/src/egldisplay/config_egldisplay.cxx index 2f8e99cc0f..3f2dbb6c03 100644 --- a/panda/src/egldisplay/config_egldisplay.cxx +++ b/panda/src/egldisplay/config_egldisplay.cxx @@ -45,7 +45,9 @@ init_libegldisplay() { initialized = true; eglGraphicsPipe::init_type(); +#ifdef HAVE_X11 eglGraphicsWindow::init_type(); +#endif eglGraphicsStateGuardian::init_type(); GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr(); diff --git a/panda/src/egldisplay/eglGraphicsBuffer.cxx b/panda/src/egldisplay/eglGraphicsBuffer.cxx index a0cf71f1fa..ba1048b23a 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..118ad02b5d 100644 --- a/panda/src/egldisplay/eglGraphicsPipe.cxx +++ b/panda/src/egldisplay/eglGraphicsPipe.cxx @@ -25,19 +25,32 @@ 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 (!eglBindAPI(EGL_OPENGL_ES_API)) { egldisplay_cat.error() << "Couldn't bind EGL to the OpenGL ES API: " << get_egl_error_string(eglGetError()) << "\n"; + _is_valid = false; + return; } + + // Even if we don't have an X11 display, we can still render headless. + _is_valid = true; } /** @@ -110,6 +123,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,6 +138,9 @@ 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 @@ -184,6 +204,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 +222,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..f5ad026138 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" @@ -42,14 +49,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 +71,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 +89,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 31c1069d46..d90cb410e3 100644 --- a/panda/src/egldisplay/eglGraphicsStateGuardian.cxx +++ b/panda/src/egldisplay/eglGraphicsStateGuardian.cxx @@ -33,11 +33,7 @@ eglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *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 +47,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 +101,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,16 +119,12 @@ 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[] = { @@ -150,7 +134,7 @@ choose_pixel_format(const FrameBufferProperties &properties, #ifdef OPENGLES_2 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, #endif - EGL_SURFACE_TYPE, EGL_DONT_CARE, + EGL_SURFACE_TYPE, need_window ? EGL_WINDOW_BIT : EGL_DONT_CARE, EGL_NONE }; @@ -206,9 +190,15 @@ 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() @@ -222,7 +212,10 @@ choose_pixel_format(const FrameBufferProperties &properties, #endif int err = eglGetError(); if (_context && err == EGL_SUCCESS) { - if (_visual) { +#ifdef HAVE_X11 + if (!display || _visual) +#endif + { _fbprops = best_props; delete[] configs; return; @@ -234,8 +227,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() << @@ -255,12 +249,7 @@ reset() { GLESGraphicsStateGuardian::reset(); #endif - // If "Mesa" is present, assume software. However, if "Mesa DRI" is found, - // it's actually a Mesa-based OpenGL layer running over a hardware driver. - if (_gl_renderer == "Software Rasterizer" || - (_gl_renderer.find("Mesa") != std::string::npos && - _gl_renderer.find("Mesa DRI") == std::string::npos)) { - // It's Mesa, therefore probably a software context. + if (_gl_renderer == "Software Rasterizer") { _fbprops.set_force_software(1); _fbprops.set_force_hardware(0); } else { @@ -289,8 +278,10 @@ 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); +#endif #ifdef OPENGLES_2 GLES2GraphicsStateGuardian::gl_flush(); #else @@ -303,8 +294,10 @@ gl_flush() const { */ GLenum eglGraphicsStateGuardian:: gl_get_error() const { +#ifdef HAVE_X11 // This call requires synchronization with X. LightReMutexHolder holder(eglGraphicsPipe::_x_mutex); +#endif #ifdef OPENGLES_2 return GLES2GraphicsStateGuardian::gl_get_error(); #else diff --git a/panda/src/egldisplay/eglGraphicsStateGuardian.h b/panda/src/egldisplay/eglGraphicsStateGuardian.h index ab47d7adf1..ab865afb3f 100644 --- a/panda/src/egldisplay/eglGraphicsStateGuardian.h +++ b/panda/src/egldisplay/eglGraphicsStateGuardian.h @@ -16,7 +16,10 @@ #include "pandabase.h" #include "eglGraphicsPipe.h" + +#ifdef HAVE_X11 #include "get_x11.h" +#endif /** * A tiny specialization on GLESGraphicsStateGuardian to add some egl-specific @@ -33,9 +36,8 @@ public: 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 +51,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; diff --git a/panda/src/egldisplay/eglGraphicsWindow.cxx b/panda/src/egldisplay/eglGraphicsWindow.cxx index 89deb47deb..8f74e1f47e 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" @@ -44,7 +47,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; } @@ -206,7 +209,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 @@ -214,7 +217,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; } } @@ -258,3 +261,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