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)
334 std::vector<EGLint> attrib_list;
335 EGLint num_config = 0;
338 fprintf(stderr,
"Warning! Stereo OpenGL ES contexts are not supported.\n");
342 EGLDisplay prev_display = eglGetCurrentDisplay();
343 EGLSurface prev_draw = eglGetCurrentSurface(EGL_DRAW);
344 EGLSurface prev_read = eglGetCurrentSurface(EGL_READ);
345 EGLContext prev_context = eglGetCurrentContext();
347 EGLint egl_major = 0, egl_minor = 0;
349 if (!
EGL_CHK((m_display = ::eglGetDisplay(m_nativeDisplay)) != EGL_NO_DISPLAY)) {
354 const EGLBoolean init_display_result = ::eglInitialize(m_display, &egl_major, &egl_minor);
355 const EGLint init_display_error = (init_display_result) ? 0 : eglGetError();
357 if (!init_display_result || (egl_major == 0 && egl_minor == 0)) {
360 ::eglTerminate(m_display);
362 const char *egl_extension_st = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
363 assert(egl_extension_st !=
nullptr);
364 assert(egl_extension_st ==
nullptr ||
365 strstr(egl_extension_st,
"EGL_MESA_platform_surfaceless") !=
nullptr);
366 if (egl_extension_st ==
nullptr ||
367 strstr(egl_extension_st,
"EGL_MESA_platform_surfaceless") ==
nullptr)
369 egl_print_error(
"Failed to create display GPU context: ", init_display_error);
372 "Failed to create headless GPU context: No EGL_MESA_platform_surfaceless extension");
376 m_display = eglGetPlatformDisplayEXT(
377 EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY,
nullptr);
379 const EGLBoolean headless_result = ::eglInitialize(m_display, &egl_major, &egl_minor);
380 const EGLint init_headless_error = (headless_result) ? 0 : eglGetError();
382 if (!headless_result) {
383 egl_print_error(
"Failed to create display GPU context: ", init_display_error);
384 egl_print_error(
"Failed to create headless GPU context: ", init_headless_error);
390#ifdef WITH_GHOST_DEBUG
391 fprintf(stderr,
"EGL Version %d.%d\n", egl_major, egl_minor);
394 if (!
EGL_CHK(::eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT))) {
397 if (!bindAPI(m_api)) {
403 attrib_list.reserve(20);
405 if (m_api == EGL_OPENGL_ES_API && epoxy_egl_version(m_display) >= 12) {
409 if (m_contextMajorVersion == 1) {
410 attrib_list.push_back(EGL_RENDERABLE_TYPE);
411 attrib_list.push_back(EGL_OPENGL_ES_BIT);
413 else if (m_contextMajorVersion == 2) {
414 attrib_list.push_back(EGL_RENDERABLE_TYPE);
415 attrib_list.push_back(EGL_OPENGL_ES2_BIT);
417 else if (m_contextMajorVersion == 3) {
418 attrib_list.push_back(EGL_RENDERABLE_TYPE);
419 attrib_list.push_back(EGL_OPENGL_ES3_BIT_KHR);
423 "Warning! Unable to request an ES context of version %d.%d\n",
424 m_contextMajorVersion,
425 m_contextMinorVersion);
428 if (!((m_contextMajorVersion == 1) ||
429 (m_contextMajorVersion == 2 && epoxy_egl_version(m_display) >= 13) ||
430 (m_contextMajorVersion == 3 &&
431 epoxy_has_egl_extension(m_display,
"KHR_create_context")) ||
432 (m_contextMajorVersion == 3 && epoxy_egl_version(m_display) >= 15)))
435 "Warning! May not be able to create a version %d.%d ES context with version %d.%d "
437 m_contextMajorVersion,
438 m_contextMinorVersion,
444 attrib_list.push_back(EGL_RENDERABLE_TYPE);
445 attrib_list.push_back(EGL_OPENGL_BIT);
448 attrib_list.push_back(EGL_RED_SIZE);
449 attrib_list.push_back(8);
451 attrib_list.push_back(EGL_GREEN_SIZE);
452 attrib_list.push_back(8);
454 attrib_list.push_back(EGL_BLUE_SIZE);
455 attrib_list.push_back(8);
457 if (m_nativeWindow == 0) {
459 attrib_list.push_back(EGL_SURFACE_TYPE);
460 attrib_list.push_back(EGL_PBUFFER_BIT);
463 attrib_list.push_back(EGL_NONE);
465 if (!
EGL_CHK(::eglChooseConfig(m_display, &(attrib_list[0]), &m_config, 1, &num_config))) {
470 if (num_config != 1) {
474 if (m_nativeWindow != 0) {
475 std::vector<EGLint> surface_attrib_list;
476 surface_attrib_list.reserve(3);
477#ifdef WITH_GHOST_WAYLAND
484 if (epoxy_has_egl_extension(m_display,
"EGL_EXT_present_opaque")) {
485# ifndef EGL_PRESENT_OPAQUE_EXT
486# define EGL_PRESENT_OPAQUE_EXT 0x31DF
488 surface_attrib_list.push_back(EGL_PRESENT_OPAQUE_EXT);
489 surface_attrib_list.push_back(EGL_TRUE);
492 surface_attrib_list.push_back(EGL_NONE);
494 m_surface = ::eglCreateWindowSurface(
495 m_display, m_config, m_nativeWindow, surface_attrib_list.data());
496 m_surface_from_native_window =
true;
499 static const EGLint pb_attrib_list[] = {
506 m_surface = ::eglCreatePbufferSurface(m_display, m_config, pb_attrib_list);
509 if (!
EGL_CHK(m_surface != EGL_NO_SURFACE)) {
514 if (epoxy_egl_version(m_display) >= 15 ||
515 epoxy_has_egl_extension(m_display,
"KHR_create_context"))
517 if (m_api == EGL_OPENGL_API || m_api == EGL_OPENGL_ES_API) {
518 if (m_contextMajorVersion != 0) {
519 attrib_list.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
520 attrib_list.push_back(m_contextMajorVersion);
523 if (m_contextMinorVersion != 0) {
524 attrib_list.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
525 attrib_list.push_back(m_contextMinorVersion);
528 if (m_contextFlags != 0) {
529 attrib_list.push_back(EGL_CONTEXT_FLAGS_KHR);
530 attrib_list.push_back(m_contextFlags);
534 if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0) {
536 "Warning! Cannot request specific versions of %s contexts.",
540 if (m_contextFlags != 0) {
541 fprintf(stderr,
"Warning! Flags cannot be set on %s contexts.",
api_string(m_api).c_str());
545 if (m_api == EGL_OPENGL_API) {
546 if (m_contextProfileMask != 0) {
547 attrib_list.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
548 attrib_list.push_back(m_contextProfileMask);
552 if (m_contextProfileMask != 0) {
554 stderr,
"Warning! Cannot select profile for %s contexts.",
api_string(m_api).c_str());
558 if (m_api == EGL_OPENGL_API || epoxy_egl_version(m_display) >= 15) {
559 if (m_contextResetNotificationStrategy != 0) {
560 attrib_list.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR);
561 attrib_list.push_back(m_contextResetNotificationStrategy);
565 if (m_contextResetNotificationStrategy != 0) {
567 "Warning! EGL %d.%d cannot set the reset notification strategy on %s contexts.",
575 if (m_api == EGL_OPENGL_ES_API) {
576 if (m_contextMajorVersion != 0) {
577 attrib_list.push_back(EGL_CONTEXT_CLIENT_VERSION);
578 attrib_list.push_back(m_contextMajorVersion);
582 if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0) {
584 "Warning! EGL %d.%d is unable to select between versions of %s.",
591 if (m_contextFlags != 0) {
592 fprintf(stderr,
"Warning! EGL %d.%d is unable to set context flags.", egl_major, egl_minor);
594 if (m_contextProfileMask != 0) {
596 "Warning! EGL %d.%d is unable to select between profiles.",
600 if (m_contextResetNotificationStrategy != 0) {
602 "Warning! EGL %d.%d is unable to set the reset notification strategies.",
608 attrib_list.push_back(EGL_NONE);
610 m_context = ::eglCreateContext(m_display, m_config, m_sharedContext, &(attrib_list[0]));
612 if (!
EGL_CHK(m_context != EGL_NO_CONTEXT)) {
616 if (m_sharedContext == EGL_NO_CONTEXT) {
617 m_sharedContext = m_context;
622 if (!
EGL_CHK(::eglMakeCurrent(m_display, m_surface, m_surface, m_context))) {
626 if (m_nativeWindow != 0) {
628 ::eglSwapBuffers(m_display, m_surface);
634 if (prev_display != EGL_NO_DISPLAY) {
635 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)