Initial support of 'EGL_EXT_platform_wayland' extension Change-Id: I90fff2dd2c5f3984f113a6d42acaa56e8ebee2de Signed-off-by: Eugene Mutavchi <Ievgen_Mutavchi@comcast.com>
diff --git a/src/third_party/starboard/rdk/shared/system/system_egl.cc b/src/third_party/starboard/rdk/shared/system/system_egl.cc index 7eeb8ce..5149cd2 100644 --- a/src/third_party/starboard/rdk/shared/system/system_egl.cc +++ b/src/third_party/starboard/rdk/shared/system/system_egl.cc
@@ -34,9 +34,13 @@ #include "starboard/egl.h" #include "third_party/starboard/rdk/shared/application_rdk.h" +#include "third_party/starboard/rdk/shared/log_override.h" +#include <mutex> #include <essos-app.h> +EssAppPlatformDisplayType EssContextGetAppPlatformDisplayType( EssCtx *ctx ) __attribute__((weak)); + #if !defined(EGL_VERSION_1_0) || !defined(EGL_VERSION_1_1) || \ !defined(EGL_VERSION_1_2) || !defined(EGL_VERSION_1_3) || \ !defined(EGL_VERSION_1_4) @@ -45,6 +49,47 @@ namespace { +#ifdef EGL_PLATFORM_WAYLAND_EXT +static PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC gEglCreatePlatformWindowSurfaceEXT; +static PFNEGLGETPLATFORMDISPLAYEXTPROC gEglGetPlatformDisplayEXT; + +bool isExtensionSupported(const char* extension_list, const char* extension) { + int len = strlen(extension); + const char* ptr = extension_list; + while ((ptr = strstr(ptr, extension))) { + if (ptr[len] == ' ' || ptr[len] == '\0') + return true; + ptr += len; + } + return false; +} + +bool resolveEglPlatfromExtFns() { + static std::once_flag flag; + std::call_once(flag, [] { + const char* extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + if (!isExtensionSupported(extensions, "EGL_EXT_platform_wayland")) { + SB_LOG(INFO) << "Wayland EGL platform extension is not supported. Supported extensions: " << extensions; + } + else { + gEglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); + gEglCreatePlatformWindowSurfaceEXT = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); + if (!gEglGetPlatformDisplayEXT || !gEglCreatePlatformWindowSurfaceEXT) { + if (!gEglGetPlatformDisplayEXT) + SB_LOG(INFO) << "eglGetPlatformDisplayEXT is not available"; + if (!gEglCreatePlatformWindowSurfaceEXT) + SB_LOG(INFO) << "eglCreatePlatformWindowSurfaceEXT is not available"; + gEglGetPlatformDisplayEXT = nullptr; + gEglCreatePlatformWindowSurfaceEXT = nullptr; + } else { + SB_LOG(INFO) << "Successfully resolved EGL platform display extension functions."; + } + } + }); + return gEglGetPlatformDisplayEXT && gEglCreatePlatformWindowSurfaceEXT; +} +#endif + // Convenience functions that redirect to the intended function but "cast" the // type of the SbEglNative*Type parameter into the desired type. Depending on // the platform, the type of cast to use is different so either C-style casts or @@ -69,16 +114,64 @@ SbEglConfig config, SbEglNativeWindowType win, const SbEglInt32* attrib_list) { - return eglCreateWindowSurface(dpy, config, (EGLNativeWindowType)win, - attrib_list); + SbEglSurface result = EGL_NO_SURFACE; + +#ifdef EGL_PLATFORM_WAYLAND_EXT + if (gEglCreatePlatformWindowSurfaceEXT) { + result = gEglCreatePlatformWindowSurfaceEXT(dpy, config, (EGLNativeWindowType)win, + attrib_list); + if (result == EGL_NO_SURFACE) + SB_LOG(WARNING) << "eglCreatePlatformWindowSurfaceEXT failed, err: " << eglGetError(); + } +#endif + + if (result == EGL_NO_SURFACE) { + result = eglCreateWindowSurface(dpy, config, (EGLNativeWindowType)win, + attrib_list); + if (result == EGL_NO_SURFACE) + SB_LOG(ERROR) << "eglCreateWindowSurface failed, err: " << eglGetError(); + } + + return result; } SbEglDisplay SbEglGetDisplay(SbEglNativeDisplayType display_id) { NativeDisplayType display_type; EssCtx *ctx = third_party::starboard::rdk::shared::Application::Get()->GetEssCtx(); - if (EssContextGetEGLDisplayType(ctx, &display_type)) - return eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(display_type)); - return eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(display_id)); + + if (EssContextGetEGLDisplayType(ctx, &display_type) == false) { + SB_LOG(ERROR) << "EssContextGetEGLDisplayType failed! Going to try display_id=" << display_id << '.'; + display_type = reinterpret_cast<NativeDisplayType>(display_id); + } + +#ifdef EGL_PLATFORM_WAYLAND_EXT + if (EssContextGetAppPlatformDisplayType == nullptr) { + SB_LOG(INFO) << "'EssContextGetAppPlatformDisplayType' is not available. Fallback to eglGetDisplay."; + } + else if (EssContextGetAppPlatformDisplayType(ctx) != EssAppPlatformDisplayType_waylandExtension) { + SB_LOG(INFO) << "Essos app platform display type is not 'WaylandExtension' (" + << EssContextGetAppPlatformDisplayType(ctx) + << " != " + << EssAppPlatformDisplayType_waylandExtension << ")." + << " Fallback to eglGetDisplay."; + } + else if (!resolveEglPlatfromExtFns()) { + SB_LOG(INFO) << "eglGetPlatformDisplayEXT is not available or failed. Fallback to eglGetDisplay."; + } + else { + SbEglDisplay result = gEglGetPlatformDisplayEXT(EGL_PLATFORM_WAYLAND_EXT, reinterpret_cast<EGLNativeDisplayType>(display_type), nullptr); + if (result == EGL_NO_DISPLAY) { + SB_LOG(ERROR) << "eglGetPlatformDisplayEXT returned EGL_NO_DISPLAY. Fallback to eglGetDisplay."; + gEglGetPlatformDisplayEXT = nullptr; + gEglCreatePlatformWindowSurfaceEXT = nullptr; + } else { + SB_LOG(INFO) << "Using display=" << result << ", returned by eglGetPlatformDisplayEXT."; + return result; + } + } +#endif + + return eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(display_type)); } const SbEglInterface g_sb_egl_interface = {