191 EGLNativeWindowType nativeWindow,
192 EGLNativeDisplayType nativeDisplay,
193 EGLint contextProfileMask,
194 EGLint contextMajorVersion,
195 EGLint contextMinorVersion,
197 EGLint contextResetNotificationStrategy,
201 native_display_(nativeDisplay),
202 native_window_(nativeWindow),
203 context_profile_mask_(contextProfileMask),
204 context_major_version_(contextMajorVersion),
205 context_minor_version_(contextMinorVersion),
206 context_flags_(contextFlags),
207 context_reset_notification_strategy_(contextResetNotificationStrategy),
209 context_(EGL_NO_CONTEXT),
210 surface_(EGL_NO_SURFACE),
211 display_(EGL_NO_DISPLAY),
212 config_(EGL_NO_CONFIG_KHR),
215 choose_api(api, s_gl_sharedContext, s_gles_sharedContext, s_vg_sharedContext)),
216 shared_count_(
choose_api(api, s_gl_sharedCount, s_gles_sharedCount, s_vg_sharedCount)),
217 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((display_ = ::eglGetDisplay(native_display_)) != EGL_NO_DISPLAY)) {
356 const EGLBoolean init_display_result = ::eglInitialize(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(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 display_ = eglGetPlatformDisplayEXT(
379 EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY,
nullptr);
381 const EGLBoolean headless_result = ::eglInitialize(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(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT))) {
399 if (!bindAPI(api_)) {
405 attrib_list.reserve(20);
407 if (api_ == EGL_OPENGL_ES_API && epoxy_egl_version(display_) >= 12) {
411 if (context_major_version_ == 1) {
412 attrib_list.push_back(EGL_RENDERABLE_TYPE);
413 attrib_list.push_back(EGL_OPENGL_ES_BIT);
415 else if (context_major_version_ == 2) {
416 attrib_list.push_back(EGL_RENDERABLE_TYPE);
417 attrib_list.push_back(EGL_OPENGL_ES2_BIT);
419 else if (context_major_version_ == 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 context_major_version_,
427 context_minor_version_);
430 if (!((context_major_version_ == 1) ||
431 (context_major_version_ == 2 && epoxy_egl_version(display_) >= 13) ||
432 (context_major_version_ == 3 &&
433 epoxy_has_egl_extension(display_,
"KHR_create_context")) ||
434 (context_major_version_ == 3 && epoxy_egl_version(display_) >= 15)))
437 "Warning! May not be able to create a version %d.%d ES context with version %d.%d "
439 context_major_version_,
440 context_minor_version_,
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 (native_window_ == 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(display_, &(attrib_list[0]), &config_, 1, &num_config))) {
472 if (num_config != 1) {
476 if (native_window_ != 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(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 surface_ = ::eglCreateWindowSurface(
497 display_, config_, native_window_, surface_attrib_list.data());
498 surface_from_native_window_ =
true;
501 static const EGLint pb_attrib_list[] = {
508 surface_ = ::eglCreatePbufferSurface(display_, config_, pb_attrib_list);
511 if (!
EGL_CHK(surface_ != EGL_NO_SURFACE)) {
516 if (epoxy_egl_version(display_) >= 15 || epoxy_has_egl_extension(display_,
"KHR_create_context"))
518 if (api_ == EGL_OPENGL_API || api_ == EGL_OPENGL_ES_API) {
519 if (context_major_version_ != 0) {
520 attrib_list.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
521 attrib_list.push_back(context_major_version_);
524 if (context_minor_version_ != 0) {
525 attrib_list.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
526 attrib_list.push_back(context_minor_version_);
529 if (context_flags_ != 0) {
530 attrib_list.push_back(EGL_CONTEXT_FLAGS_KHR);
531 attrib_list.push_back(context_flags_);
535 if (context_major_version_ != 0 || context_minor_version_ != 0) {
537 "Warning! Cannot request specific versions of %s contexts.",
541 if (context_flags_ != 0) {
542 fprintf(stderr,
"Warning! Flags cannot be set on %s contexts.",
api_string(api_).c_str());
546 if (api_ == EGL_OPENGL_API) {
547 if (context_profile_mask_ != 0) {
548 attrib_list.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
549 attrib_list.push_back(context_profile_mask_);
553 if (context_profile_mask_ != 0) {
555 stderr,
"Warning! Cannot select profile for %s contexts.",
api_string(api_).c_str());
559 if (api_ == EGL_OPENGL_API || epoxy_egl_version(display_) >= 15) {
560 if (context_reset_notification_strategy_ != 0) {
561 attrib_list.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR);
562 attrib_list.push_back(context_reset_notification_strategy_);
566 if (context_reset_notification_strategy_ != 0) {
568 "Warning! EGL %d.%d cannot set the reset notification strategy on %s contexts.",
576 if (api_ == EGL_OPENGL_ES_API) {
577 if (context_major_version_ != 0) {
578 attrib_list.push_back(EGL_CONTEXT_CLIENT_VERSION);
579 attrib_list.push_back(context_major_version_);
583 if (context_major_version_ != 0 || context_minor_version_ != 0) {
585 "Warning! EGL %d.%d is unable to select between versions of %s.",
592 if (context_flags_ != 0) {
593 fprintf(stderr,
"Warning! EGL %d.%d is unable to set context flags.", egl_major, egl_minor);
595 if (context_profile_mask_ != 0) {
597 "Warning! EGL %d.%d is unable to select between profiles.",
601 if (context_reset_notification_strategy_ != 0) {
603 "Warning! EGL %d.%d is unable to set the reset notification strategies.",
609 attrib_list.push_back(EGL_NONE);
611 context_ = ::eglCreateContext(display_, config_, shared_context_, &(attrib_list[0]));
613 if (!
EGL_CHK(context_ != EGL_NO_CONTEXT)) {
617 if (shared_context_ == EGL_NO_CONTEXT) {
618 shared_context_ = context_;
623 if (!
EGL_CHK(::eglMakeCurrent(display_, surface_, surface_, context_))) {
634 if (native_window_ != 0) {
636 ::eglSwapBuffers(display_, surface_);
643 if (prev_display != EGL_NO_DISPLAY) {
644 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, const GHOST_ContextParams &context_params, EGLNativeWindowType nativeWindow, EGLNativeDisplayType nativeDisplay, EGLint contextProfileMask, EGLint contextMajorVersion, EGLint contextMinorVersion, EGLint contextFlags, EGLint contextResetNotificationStrategy, EGLenum api)