Skip to content

Commit

Permalink
egldisplay: Support creating headless GLES contexts
Browse files Browse the repository at this point in the history
See #557
  • Loading branch information
rdb committed May 19, 2020
1 parent c218af2 commit fbc4947
Show file tree
Hide file tree
Showing 12 changed files with 120 additions and 62 deletions.
10 changes: 6 additions & 4 deletions makepanda/makepanda.py
Original file line number Diff line number Diff line change
Expand Up @@ -4494,13 +4494,14 @@ def get_config_express():
# 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')
Expand All @@ -4512,13 +4513,14 @@ def get_config_express():
# 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')
Expand Down
2 changes: 2 additions & 0 deletions panda/src/egldisplay/config_egldisplay.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
8 changes: 5 additions & 3 deletions panda/src/egldisplay/eglGraphicsBuffer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down Expand Up @@ -159,15 +159,15 @@ 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
// with the old gsg.
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;
}
}
Expand All @@ -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(),
Expand Down
8 changes: 8 additions & 0 deletions panda/src/egldisplay/eglGraphicsPipe.I
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,11 @@
* @author rdb
* @date 2009-05-21
*/

/**
*
*/
INLINE EGLDisplay eglGraphicsPipe::
get_egl_display() const {
return _egl_display;
}
29 changes: 28 additions & 1 deletion panda/src/egldisplay/eglGraphicsPipe.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -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)||
Expand All @@ -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
Expand Down Expand Up @@ -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)||
Expand All @@ -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.
Expand Down
23 changes: 14 additions & 9 deletions panda/src/egldisplay/eglGraphicsPipe.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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,
Expand All @@ -62,16 +71,16 @@ class eglGraphicsPipe : public x11GraphicsPipe {
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();
Expand All @@ -80,10 +89,6 @@ class eglGraphicsPipe : public x11GraphicsPipe {

private:
static TypeHandle _type_handle;

friend class eglGraphicsBuffer;
friend class eglGraphicsPixmap;
friend class eglGraphicsWindow;
};

#include "eglGraphicsPipe.I"
Expand Down
13 changes: 9 additions & 4 deletions panda/src/egldisplay/eglGraphicsPixmap.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
*/

#include "eglGraphicsPixmap.h"

#ifdef HAVE_X11

#include "eglGraphicsWindow.h"
#include "eglGraphicsStateGuardian.h"
#include "config_egldisplay.h"
Expand All @@ -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;
Expand Down Expand Up @@ -167,15 +169,15 @@ 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
// with the old gsg.
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;
}
}
Expand All @@ -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())) {
Expand Down Expand Up @@ -241,3 +244,5 @@ open_buffer() {
_is_valid = true;
return true;
}

#endif // HAVE_X11
4 changes: 4 additions & 0 deletions panda/src/egldisplay/eglGraphicsPixmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#include "pandabase.h"

#ifdef HAVE_X11

#include "eglGraphicsPipe.h"
#include "graphicsBuffer.h"

Expand Down Expand Up @@ -67,4 +69,6 @@ class eglGraphicsPixmap : public GraphicsBuffer {
static TypeHandle _type_handle;
};

#endif // HAVE_X11

#endif
Loading

0 comments on commit fbc4947

Please sign in to comment.