191 EGLNativeWindowType nativeWindow,
192 EGLNativeDisplayType nativeDisplay,
193 EGLint contextProfileMask,
194 EGLint contextMajorVersion,
195 EGLint contextMinorVersion,
197 EGLint contextResetNotificationStrategy,
201 m_nativeDisplay(nativeDisplay),
202 m_nativeWindow(nativeWindow),
203 m_contextProfileMask(contextProfileMask),
204 m_contextMajorVersion(contextMajorVersion),
205 m_contextMinorVersion(contextMinorVersion),
206 m_contextFlags(contextFlags),
207 m_contextResetNotificationStrategy(contextResetNotificationStrategy),
209 m_context(EGL_NO_CONTEXT),
210 m_surface(EGL_NO_SURFACE),
211 m_display(EGL_NO_DISPLAY),
212 m_config(EGL_NO_CONFIG_KHR),
215 choose_api(api, s_gl_sharedContext, s_gles_sharedContext, s_vg_sharedContext)),
216 m_sharedCount(
choose_api(api, s_gl_sharedCount, s_gles_sharedCount, s_vg_sharedCount)),
217 m_surface_from_native_window(
false)
336 std::vector<EGLint> attrib_list;
337 EGLint num_config = 0;
340 fprintf(stderr,
"Warning! Stereo OpenGL ES contexts are not supported.\n");
344 EGLDisplay prev_display = eglGetCurrentDisplay();
345 EGLSurface prev_draw = eglGetCurrentSurface(EGL_DRAW);
346 EGLSurface prev_read = eglGetCurrentSurface(EGL_READ);
347 EGLContext prev_context = eglGetCurrentContext();
349 EGLint egl_major = 0, egl_minor = 0;
351 if (!
EGL_CHK((m_display = ::eglGetDisplay(m_nativeDisplay)) != EGL_NO_DISPLAY)) {
356 const EGLBoolean init_display_result = ::eglInitialize(m_display, &egl_major, &egl_minor);
357 const EGLint init_display_error = (init_display_result) ? 0 : eglGetError();
359 if (!init_display_result || (egl_major == 0 && egl_minor == 0)) {
362 ::eglTerminate(m_display);
364 const char *egl_extension_st = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
365 assert(egl_extension_st !=
nullptr);
366 assert(egl_extension_st ==
nullptr ||
367 strstr(egl_extension_st,
"EGL_MESA_platform_surfaceless") !=
nullptr);
368 if (egl_extension_st ==
nullptr ||
369 strstr(egl_extension_st,
"EGL_MESA_platform_surfaceless") ==
nullptr)
371 egl_print_error(
"Failed to create display GPU context: ", init_display_error);
374 "Failed to create headless GPU context: No EGL_MESA_platform_surfaceless extension");
378 m_display = eglGetPlatformDisplayEXT(
379 EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY,
nullptr);
381 const EGLBoolean headless_result = ::eglInitialize(m_display, &egl_major, &egl_minor);
382 const EGLint init_headless_error = (headless_result) ? 0 : eglGetError();
384 if (!headless_result) {
385 egl_print_error(
"Failed to create display GPU context: ", init_display_error);
386 egl_print_error(
"Failed to create headless GPU context: ", init_headless_error);
392#ifdef WITH_GHOST_DEBUG
393 fprintf(stderr,
"EGL Version %d.%d\n", egl_major, egl_minor);
396 if (!
EGL_CHK(::eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT))) {
399 if (!bindAPI(m_api)) {
405 attrib_list.reserve(20);
407 if (m_api == EGL_OPENGL_ES_API && epoxy_egl_version(m_display) >= 12) {
411 if (m_contextMajorVersion == 1) {
412 attrib_list.push_back(EGL_RENDERABLE_TYPE);
413 attrib_list.push_back(EGL_OPENGL_ES_BIT);
415 else if (m_contextMajorVersion == 2) {
416 attrib_list.push_back(EGL_RENDERABLE_TYPE);
417 attrib_list.push_back(EGL_OPENGL_ES2_BIT);
419 else if (m_contextMajorVersion == 3) {
420 attrib_list.push_back(EGL_RENDERABLE_TYPE);
421 attrib_list.push_back(EGL_OPENGL_ES3_BIT_KHR);
425 "Warning! Unable to request an ES context of version %d.%d\n",
426 m_contextMajorVersion,
427 m_contextMinorVersion);
430 if (!((m_contextMajorVersion == 1) ||
431 (m_contextMajorVersion == 2 && epoxy_egl_version(m_display) >= 13) ||
432 (m_contextMajorVersion == 3 &&
433 epoxy_has_egl_extension(m_display,
"KHR_create_context")) ||
434 (m_contextMajorVersion == 3 && epoxy_egl_version(m_display) >= 15)))
437 "Warning! May not be able to create a version %d.%d ES context with version %d.%d "
439 m_contextMajorVersion,
440 m_contextMinorVersion,
446 attrib_list.push_back(EGL_RENDERABLE_TYPE);
447 attrib_list.push_back(EGL_OPENGL_BIT);
450 attrib_list.push_back(EGL_RED_SIZE);
451 attrib_list.push_back(8);
453 attrib_list.push_back(EGL_GREEN_SIZE);
454 attrib_list.push_back(8);
456 attrib_list.push_back(EGL_BLUE_SIZE);
457 attrib_list.push_back(8);
459 if (m_nativeWindow == 0) {
461 attrib_list.push_back(EGL_SURFACE_TYPE);
462 attrib_list.push_back(EGL_PBUFFER_BIT);
465 attrib_list.push_back(EGL_NONE);
467 if (!
EGL_CHK(::eglChooseConfig(m_display, &(attrib_list[0]), &m_config, 1, &num_config))) {
472 if (num_config != 1) {
476 if (m_nativeWindow != 0) {
477 std::vector<EGLint> surface_attrib_list;
478 surface_attrib_list.reserve(3);
479#ifdef WITH_GHOST_WAYLAND
486 if (epoxy_has_egl_extension(m_display,
"EGL_EXT_present_opaque")) {
487# ifndef EGL_PRESENT_OPAQUE_EXT
488# define EGL_PRESENT_OPAQUE_EXT 0x31DF
490 surface_attrib_list.push_back(EGL_PRESENT_OPAQUE_EXT);
491 surface_attrib_list.push_back(EGL_TRUE);
494 surface_attrib_list.push_back(EGL_NONE);
496 m_surface = ::eglCreateWindowSurface(
497 m_display, m_config, m_nativeWindow, surface_attrib_list.data());
498 m_surface_from_native_window =
true;
501 static const EGLint pb_attrib_list[] = {
508 m_surface = ::eglCreatePbufferSurface(m_display, m_config, pb_attrib_list);
511 if (!
EGL_CHK(m_surface != EGL_NO_SURFACE)) {
516 if (epoxy_egl_version(m_display) >= 15 ||
517 epoxy_has_egl_extension(m_display,
"KHR_create_context"))
519 if (m_api == EGL_OPENGL_API || m_api == EGL_OPENGL_ES_API) {
520 if (m_contextMajorVersion != 0) {
521 attrib_list.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
522 attrib_list.push_back(m_contextMajorVersion);
525 if (m_contextMinorVersion != 0) {
526 attrib_list.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
527 attrib_list.push_back(m_contextMinorVersion);
530 if (m_contextFlags != 0) {
531 attrib_list.push_back(EGL_CONTEXT_FLAGS_KHR);
532 attrib_list.push_back(m_contextFlags);
536 if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0) {
538 "Warning! Cannot request specific versions of %s contexts.",
542 if (m_contextFlags != 0) {
543 fprintf(stderr,
"Warning! Flags cannot be set on %s contexts.",
api_string(m_api).c_str());
547 if (m_api == EGL_OPENGL_API) {
548 if (m_contextProfileMask != 0) {
549 attrib_list.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
550 attrib_list.push_back(m_contextProfileMask);
554 if (m_contextProfileMask != 0) {
556 stderr,
"Warning! Cannot select profile for %s contexts.",
api_string(m_api).c_str());
560 if (m_api == EGL_OPENGL_API || epoxy_egl_version(m_display) >= 15) {
561 if (m_contextResetNotificationStrategy != 0) {
562 attrib_list.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR);
563 attrib_list.push_back(m_contextResetNotificationStrategy);
567 if (m_contextResetNotificationStrategy != 0) {
569 "Warning! EGL %d.%d cannot set the reset notification strategy on %s contexts.",
577 if (m_api == EGL_OPENGL_ES_API) {
578 if (m_contextMajorVersion != 0) {
579 attrib_list.push_back(EGL_CONTEXT_CLIENT_VERSION);
580 attrib_list.push_back(m_contextMajorVersion);
584 if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0) {
586 "Warning! EGL %d.%d is unable to select between versions of %s.",
593 if (m_contextFlags != 0) {
594 fprintf(stderr,
"Warning! EGL %d.%d is unable to set context flags.", egl_major, egl_minor);
596 if (m_contextProfileMask != 0) {
598 "Warning! EGL %d.%d is unable to select between profiles.",
602 if (m_contextResetNotificationStrategy != 0) {
604 "Warning! EGL %d.%d is unable to set the reset notification strategies.",
610 attrib_list.push_back(EGL_NONE);
612 m_context = ::eglCreateContext(m_display, m_config, m_sharedContext, &(attrib_list[0]));
614 if (!
EGL_CHK(m_context != EGL_NO_CONTEXT)) {
618 if (m_sharedContext == EGL_NO_CONTEXT) {
619 m_sharedContext = m_context;
624 if (!
EGL_CHK(::eglMakeCurrent(m_display, m_surface, m_surface, m_context))) {
628 if (m_nativeWindow != 0) {
630 ::eglSwapBuffers(m_display, m_surface);
637 if (prev_display != EGL_NO_DISPLAY) {
638 EGL_CHK(eglMakeCurrent(prev_display, prev_draw, prev_read, prev_context));
static bool egl_chk(bool result, const char *file=nullptr, int line=0, const char *text=nullptr)
GHOST_ContextEGL(const GHOST_System *const system, bool stereoVisual, EGLNativeWindowType nativeWindow, EGLNativeDisplayType nativeDisplay, EGLint contextProfileMask, EGLint contextMajorVersion, EGLint contextMinorVersion, EGLint contextFlags, EGLint contextResetNotificationStrategy, EGLenum api)