Browse Source

egldisplay: Backport changes for creating headless EGL contexts

Backport of fbc49474557fe7b2ec1875ebb1cfb62e96e7f103 and 9f1289b4920074feb7f0b9b203d2a5b6e811c816

See #557
rdb 5 years ago
parent
commit
8924b77da4

+ 28 - 4
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')

+ 16 - 3
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;
 }

+ 7 - 3
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
 }
 

+ 6 - 4
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

+ 5 - 3
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(),

+ 8 - 0
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;
+}

+ 44 - 3
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.

+ 20 - 10
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 <GLES/egl.h>
   #include "post_x11_include.h"
+#else
+  #include "glgsg.h"
+  #include "pre_x11_include.h"
+  #include <EGL/egl.h>
+  #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"

+ 9 - 4
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

+ 4 - 0
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

+ 62 - 56
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";

+ 19 - 20
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();

+ 8 - 3
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

+ 4 - 0
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