22#include <EGL/eglext.h>
25(
"egl-device-index", -1,
26 PRC_DESC(
"Selects which EGL device index is used to create the EGL display in "
27 "a headless configuration. The special value -1 selects the default "
38 vector_string extensions;
39 bool supports_platform_device =
false;
40 bool supports_device_enumeration =
false;
41 const char *ext_ptr = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
42 if (ext_ptr !=
nullptr) {
45 if (egldisplay_cat.is_debug()) {
46 std::ostream &out = egldisplay_cat.debug()
47 <<
"Supported EGL client extensions:\n";
49 for (
const std::string &extension : extensions) {
50 out <<
" " << extension <<
"\n";
54 if (std::find(extensions.begin(), extensions.end(),
"EGL_EXT_platform_device") != extensions.end()) {
55 supports_platform_device =
true;
57 if (std::find(extensions.begin(), extensions.end(),
"EGL_EXT_device_enumeration") != extensions.end()) {
58 supports_device_enumeration =
true;
61 else if (egldisplay_cat.is_debug()) {
63 egldisplay_cat.debug()
64 <<
"EGL client extensions not supported.\n";
70 if (index >= 0 && supports_platform_device && supports_device_enumeration) {
71 PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
72 (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress(
"eglGetPlatformDisplayEXT");
74 PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT =
75 (PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress(
"eglQueryDevicesEXT");
77 EGLint num_devices = 0;
78 if (eglQueryDevicesEXT !=
nullptr &&
79 eglQueryDevicesEXT(0,
nullptr, &num_devices) &&
81 EGLDeviceEXT *devices = (EGLDeviceEXT *)alloca(
sizeof(EGLDeviceEXT) * num_devices);
82 eglQueryDevicesEXT(num_devices, devices, &num_devices);
84 if (index >= num_devices) {
85 egldisplay_cat.error()
86 <<
"Requested EGL device index " << index <<
" does not exist ("
87 <<
"there are only " << num_devices <<
" devices)\n";
92 if (egldisplay_cat.is_debug()) {
93 egldisplay_cat.debug()
94 <<
"Found " << num_devices <<
" EGL devices, using device index "
98 _egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, devices[index],
nullptr);
100 if (_egl_display && !eglInitialize(_egl_display, &major, &minor)) {
101 egldisplay_cat.error()
102 <<
"Couldn't initialize EGL platform display " << index <<
": "
104 _egl_display = EGL_NO_DISPLAY;
112 _egl_display = eglGetDisplay((NativeDisplayType) _display);
114 _egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
116 if (_egl_display && !eglInitialize(_egl_display, &major, &minor)) {
117 egldisplay_cat.warning()
118 <<
"Couldn't initialize the default EGL display: "
120 _egl_display = EGL_NO_DISPLAY;
123 if (!_egl_display && supports_platform_device && supports_device_enumeration) {
124 PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT =
125 (PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress(
"eglQueryDevicesEXT");
127 EGLint num_devices = 0;
128 if (eglQueryDevicesEXT !=
nullptr &&
129 eglQueryDevicesEXT(0,
nullptr, &num_devices) &&
131 EGLDeviceEXT *devices = (EGLDeviceEXT *)alloca(
sizeof(EGLDeviceEXT) * num_devices);
132 eglQueryDevicesEXT(num_devices, devices, &num_devices);
134 if (egldisplay_cat.is_debug()) {
135 egldisplay_cat.debug()
136 <<
"Found " << num_devices <<
" EGL devices.\n";
139 PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
140 (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress(
"eglGetPlatformDisplayEXT");
142 if (eglGetPlatformDisplayEXT !=
nullptr) {
143 for (EGLint i = 0; i < num_devices && !_egl_display; ++i) {
144 _egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, devices[i],
nullptr);
146 if (_egl_display && !eglInitialize(_egl_display, &major, &minor)) {
147 egldisplay_cat.warning()
148 <<
"Couldn't initialize EGL platform display " << i <<
": "
150 _egl_display = EGL_NO_DISPLAY;
159 egldisplay_cat.error()
160 <<
"Failed to find or initialize a suitable EGL display connection.\n";
165 if (egldisplay_cat.is_debug()) {
166 egldisplay_cat.debug()
167 <<
"Successfully initialized EGL display, got version " << major <<
"." << minor <<
"\n";
170#if defined(OPENGLES_1) || defined(OPENGLES_2)
171 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
172 egldisplay_cat.error()
173 <<
"Couldn't bind EGL to the OpenGL ES API: "
176 if (!eglBindAPI(EGL_OPENGL_API)) {
177 egldisplay_cat.error()
178 <<
"Couldn't bind EGL to the OpenGL API: "
195 if (!eglTerminate(_egl_display)) {
196 egldisplay_cat.error() <<
"Failed to terminate EGL display: "
210#if defined(OPENGLES_1) || defined(OPENGLES_2)
230make_output(
const std::string &name,
246 DCAST_INTO_R(eglgsg, gsg,
nullptr);
267 if (((flags&BF_require_parasite)!=0)||
268 ((flags&BF_refuse_window)!=0)||
269 ((flags&BF_resizeable)!=0)||
270 ((flags&BF_size_track_host)!=0)||
271 ((flags&BF_rtt_cumulative)!=0)||
272 ((flags&BF_can_bind_color)!=0)||
273 ((flags&BF_can_bind_every)!=0)) {
276 return new eglGraphicsWindow(engine,
this, name, fb_prop, win_prop,
287 ((flags&BF_require_parasite)!=0)||
288 ((flags&BF_require_window)!=0)) {
293 if ((flags & BF_fb_props_optional)==0) {
294 if (fb_prop.get_indexed_color() > 0 ||
295 fb_prop.get_back_buffers() > 0 ||
296 fb_prop.get_accum_bits() > 0) {
303 (eglgsg->is_valid()) &&
304 (!eglgsg->needs_reset()) &&
305 (eglgsg->_supports_framebuffer_object) &&
306 (eglgsg->_glDrawBuffers != 0)&&
311 return new GLES2GraphicsBuffer(engine,
this, name, fb_prop, win_prop,
313#elif defined(OPENGLES_1)
314 return new GLESGraphicsBuffer(engine,
this, name, fb_prop, win_prop,
317 return new GLGraphicsBuffer(engine,
this, name, fb_prop, win_prop,
324 if (((flags&BF_require_parasite)!=0)||
325 ((flags&BF_require_window)!=0)||
326 ((flags&BF_size_track_host)!=0)) {
331 if (((flags&BF_rtt_cumulative)!=0)||
332 ((flags&BF_can_bind_every)!=0)) {
349 if (((flags&BF_require_parasite)!=0)||
350 ((flags&BF_require_window)!=0)||
351 ((flags&BF_resizeable)!=0)||
352 ((flags&BF_size_track_host)!=0)) {
356 if (((flags&BF_rtt_cumulative)!=0)||
357 ((flags&BF_can_bind_every)!=0)) {
361 return new eglGraphicsPixmap(engine,
this, name, fb_prop, win_prop,
This is a convenience class to specialize ConfigVariable as an integer type.
get_value
Returns the variable's value.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
bool is_basic() const
Returns true if the properties are extremely basic.
This class is the main interface to controlling the render process.
This is a base class for the various different classes that represent the result of a frame of render...
An object to create GraphicsOutputs that share a particular 3-D API.
Encapsulates all the communication with a particular instance of a given rendering backend.
TypeHandle is the identifier used to differentiate C++ class types.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
An offscreen buffer in the EGL environment.
This graphics pipe represents the interface for creating OpenGL ES graphics windows on an X-based (e....
virtual std::string get_interface_name() const
Returns the name of the rendering interface associated with this GraphicsPipe.
A tiny specialization on GLESGraphicsStateGuardian to add some egl-specific information.
const std::string get_egl_error_string(int error)
Returns the given EGL error as string.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int extract_words(const string &str, vector_string &words)
Divides the string into a number of words according to whitespace.