From 930b26417d2a183b1a826ecf2fee669dbe15af3f Mon Sep 17 00:00:00 2001 From: Jamie Madill Date: Mon, 23 Mar 2020 14:47:03 -0400 Subject: [PATCH] Allow tests to run on native EGL. Adds support for Linux and Android native EGL testing. This can be useful for doing performance comparisons of ANGLE vs a native GL driver. Only enabled for the trace perf tests due to limitations in the test harness. Bug: angleproject:4596 Change-Id: Iba6d3ccd7c1275cf095893fab824a0ea33dc3a79 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2116254 Commit-Queue: Jamie Madill Reviewed-by: Yuly Novikov --- samples/sample_util/SampleApplication.cpp | 3 +- src/common/system_utils.h | 1 + src/common/system_utils_posix.cpp | 26 +++--- src/common/system_utils_win32.cpp | 36 +++++--- src/common/system_utils_winuwp.cpp | 42 +++++---- .../egl_tests/EGLContextCompatibilityTest.cpp | 2 +- src/tests/gl_tests/ProgramBinaryTest.cpp | 4 +- src/tests/perf_tests/ANGLEPerfTest.cpp | 9 +- src/tests/perf_tests/DrawCallPerfParams.h | 7 ++ src/tests/perf_tests/TracePerfTest.cpp | 2 +- src/tests/test_utils/ANGLETest.cpp | 87 +++++++++++++------ src/tests/test_utils/ANGLETest.h | 15 ++-- src/tests/test_utils/angle_test_configs.cpp | 26 +++++- src/tests/test_utils/angle_test_configs.h | 16 ++-- .../test_utils/angle_test_instantiate.cpp | 61 +++++++++---- util/EGLPlatformParameters.h | 11 +++ util/EGLWindow.cpp | 65 +++++++++----- util/EGLWindow.h | 3 + util/windows/WGLWindow.cpp | 6 ++ util/windows/WGLWindow.h | 1 + 20 files changed, 295 insertions(+), 128 deletions(-) diff --git a/samples/sample_util/SampleApplication.cpp b/samples/sample_util/SampleApplication.cpp index ff9af44b7..2c5e33c5e 100644 --- a/samples/sample_util/SampleApplication.cpp +++ b/samples/sample_util/SampleApplication.cpp @@ -155,7 +155,8 @@ int SampleApplication::run() configParams.depthBits = 24; configParams.stencilBits = 8; - if (!mEGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(), mPlatformParams, configParams)) + if (!mEGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(), angle::GLESDriverType::AngleEGL, + mPlatformParams, configParams)) { return -1; } diff --git a/src/common/system_utils.h b/src/common/system_utils.h index 9dda14437..3c472a80c 100644 --- a/src/common/system_utils.h +++ b/src/common/system_utils.h @@ -68,6 +68,7 @@ enum class SearchType }; Library *OpenSharedLibrary(const char *libraryName, SearchType searchType); +Library *OpenSharedLibraryWithExtension(const char *libraryName); // Returns true if the process is currently being debugged. bool IsDebuggerAttached(); diff --git a/src/common/system_utils_posix.cpp b/src/common/system_utils_posix.cpp index f9c01959f..a27b8db1f 100644 --- a/src/common/system_utils_posix.cpp +++ b/src/common/system_utils_posix.cpp @@ -72,19 +72,11 @@ std::string GetHelperExecutableDir() class PosixLibrary : public Library { public: - PosixLibrary(const char *libraryName, SearchType searchType) + PosixLibrary(const std::string &fullPath) : mModule(dlopen(fullPath.c_str(), RTLD_NOW)) { - std::string directory; - if (searchType == SearchType::ApplicationDir) - { - directory = GetHelperExecutableDir(); - } - - std::string fullPath = directory + libraryName + "." + GetSharedLibraryExtension(); - mModule = dlopen(fullPath.c_str(), RTLD_NOW); if (!mModule) { - std::cerr << "Failed to load " << libraryName << ": " << dlerror() << std::endl; + std::cerr << "Failed to load " << fullPath << ": " << dlerror() << std::endl; } } @@ -114,7 +106,19 @@ class PosixLibrary : public Library Library *OpenSharedLibrary(const char *libraryName, SearchType searchType) { - return new PosixLibrary(libraryName, searchType); + std::string directory; + if (searchType == SearchType::ApplicationDir) + { + directory = GetHelperExecutableDir(); + } + + std::string fullPath = directory + libraryName + "." + GetSharedLibraryExtension(); + return new PosixLibrary(fullPath); +} + +Library *OpenSharedLibraryWithExtension(const char *libraryName) +{ + return new PosixLibrary(libraryName); } bool IsDirectory(const char *filename) diff --git a/src/common/system_utils_win32.cpp b/src/common/system_utils_win32.cpp index d6504e440..fbe61df98 100644 --- a/src/common/system_utils_win32.cpp +++ b/src/common/system_utils_win32.cpp @@ -42,19 +42,14 @@ class Win32Library : public Library public: Win32Library(const char *libraryName, SearchType searchType) { - char buffer[MAX_PATH]; - int ret = snprintf(buffer, MAX_PATH, "%s.%s", libraryName, GetSharedLibraryExtension()); - if (ret > 0 && ret < MAX_PATH) + switch (searchType) { - switch (searchType) - { - case SearchType::ApplicationDir: - mModule = LoadLibraryA(buffer); - break; - case SearchType::SystemDir: - mModule = LoadLibraryExA(buffer, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); - break; - } + case SearchType::ApplicationDir: + mModule = LoadLibraryA(libraryName); + break; + case SearchType::SystemDir: + mModule = LoadLibraryExA(libraryName, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); + break; } } @@ -84,6 +79,21 @@ class Win32Library : public Library Library *OpenSharedLibrary(const char *libraryName, SearchType searchType) { - return new Win32Library(libraryName, searchType); + char buffer[MAX_PATH]; + int ret = snprintf(buffer, MAX_PATH, "%s.%s", libraryName, GetSharedLibraryExtension()); + if (ret > 0 && ret < MAX_PATH) + { + return new Win32Library(buffer, searchType); + } + else + { + fprintf(stderr, "Error loading shared library: 0x%x", ret); + return nullptr; + } +} + +Library *OpenSharedLibraryWithExtension(const char *libraryName) +{ + return new Win32Library(libraryName, SearchType::SystemDir); } } // namespace angle diff --git a/src/common/system_utils_winuwp.cpp b/src/common/system_utils_winuwp.cpp index b6da208cc..b3bbb7838 100644 --- a/src/common/system_utils_winuwp.cpp +++ b/src/common/system_utils_winuwp.cpp @@ -35,23 +35,17 @@ class UwpLibrary : public Library public: UwpLibrary(const char *libraryName, SearchType searchType) { - char buffer[MAX_PATH]; - int ret = snprintf(buffer, MAX_PATH, "%s.%s", libraryName, GetSharedLibraryExtension()); - std::wstring_convert> converter; - std::wstring wideBuffer = converter.from_bytes(buffer); + std::wstring wideBuffer = converter.from_bytes(libraryName); - if (ret > 0 && ret < MAX_PATH) + switch (searchType) { - switch (searchType) - { - case SearchType::ApplicationDir: - mModule = LoadPackagedLibrary(wideBuffer.c_str(), 0); - break; - case SearchType::SystemDir: - // Not supported in UWP - break; - } + case SearchType::ApplicationDir: + mModule = LoadPackagedLibrary(wideBuffer.c_str(), 0); + break; + case SearchType::SystemDir: + // Not supported in UWP + break; } } @@ -81,6 +75,24 @@ class UwpLibrary : public Library Library *OpenSharedLibrary(const char *libraryName, SearchType searchType) { - return new UwpLibrary(libraryName, searchType); + char buffer[MAX_PATH]; + int ret = snprintf(buffer, MAX_PATH, "%s.%s", libraryName, GetSharedLibraryExtension()); + + if (ret > 0 && ret < MAX_PATH) + { + return new UwpLibrary(buffer, searchType); + } + else + { + fprintf(stderr, "Error loading shared library: 0x%x", ret); + return nullptr; + } +} + +Library *OpenSharedLibraryWithExtension(const char *libraryName) +{ + // SystemDir is not implemented in UWP. + fprintf(stderr, "Error loading shared library with extension.\n"); + return nullptr; } } // namespace angle diff --git a/src/tests/egl_tests/EGLContextCompatibilityTest.cpp b/src/tests/egl_tests/EGLContextCompatibilityTest.cpp index 04ffdc2bf..17208fd25 100644 --- a/src/tests/egl_tests/EGLContextCompatibilityTest.cpp +++ b/src/tests/egl_tests/EGLContextCompatibilityTest.cpp @@ -478,7 +478,7 @@ void RegisterContextCompatibilityTests() EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, }}; - LoadEntryPointsWithUtilLoader(); + LoadEntryPointsWithUtilLoader(angle::GLESDriverType::AngleEGL); if (eglGetPlatformDisplayEXT == nullptr) { diff --git a/src/tests/gl_tests/ProgramBinaryTest.cpp b/src/tests/gl_tests/ProgramBinaryTest.cpp index 6cc1efde7..9616b1361 100644 --- a/src/tests/gl_tests/ProgramBinaryTest.cpp +++ b/src/tests/gl_tests/ProgramBinaryTest.cpp @@ -1108,8 +1108,8 @@ class ProgramBinariesAcrossPlatforms : public testing::TestWithParaminitializeGL(mOSWindow, mEntryPointsLib.get(), param.eglParameters, - configParams); + bool result = eglWindow->initializeGL(mOSWindow, mEntryPointsLib.get(), param.driver, + param.eglParameters, configParams); if (!result) { EGLWindow::Delete(&eglWindow); diff --git a/src/tests/perf_tests/ANGLEPerfTest.cpp b/src/tests/perf_tests/ANGLEPerfTest.cpp index 2425ef106..3bc0fd786 100644 --- a/src/tests/perf_tests/ANGLEPerfTest.cpp +++ b/src/tests/perf_tests/ANGLEPerfTest.cpp @@ -422,8 +422,14 @@ ANGLERenderTest::ANGLERenderTest(const std::string &name, const RenderTestParams angle::SearchType::ApplicationDir)); break; case angle::GLESDriverType::SystemEGL: +#if defined(ANGLE_USE_UTIL_LOADER) && !defined(ANGLE_PLATFORM_WINDOWS) + mGLWindow = EGLWindow::New(testParams.majorVersion, testParams.minorVersion); + mEntryPointsLib.reset( + angle::OpenSharedLibraryWithExtension(GetNativeEGLLibraryNameWithExtension())); +#else std::cerr << "Not implemented." << std::endl; mSkipTest = true; +#endif // defined(ANGLE_USE_UTIL_LOADER) && !defined(ANGLE_PLATFORM_WINDOWS) break; case angle::GLESDriverType::SystemWGL: #if defined(ANGLE_USE_UTIL_LOADER) && defined(ANGLE_PLATFORM_WINDOWS) @@ -494,7 +500,8 @@ void ANGLERenderTest::SetUp() EGLPlatformParameters withMethods = mTestParams.eglParameters; withMethods.platformMethods = &mPlatformMethods; - if (!mGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(), withMethods, mConfigParams)) + if (!mGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(), mTestParams.driver, withMethods, + mConfigParams)) { mSkipTest = true; FAIL() << "Failed initializing GL Window"; diff --git a/src/tests/perf_tests/DrawCallPerfParams.h b/src/tests/perf_tests/DrawCallPerfParams.h index 6c6678765..de1f171b8 100644 --- a/src/tests/perf_tests/DrawCallPerfParams.h +++ b/src/tests/perf_tests/DrawCallPerfParams.h @@ -78,6 +78,13 @@ ParamsT WGL(const ParamsT &in) return out; } +template +ParamsT EGL(const ParamsT &in) +{ + ParamsT out = in; + out.driver = angle::GLESDriverType::SystemEGL; + return out; +} } // namespace params #endif // TESTS_PERF_TESTS_DRAW_CALL_PERF_PARAMS_H_ diff --git a/src/tests/perf_tests/TracePerfTest.cpp b/src/tests/perf_tests/TracePerfTest.cpp index 77cdd9c1f..1646ceaf9 100644 --- a/src/tests/perf_tests/TracePerfTest.cpp +++ b/src/tests/perf_tests/TracePerfTest.cpp @@ -314,7 +314,7 @@ using P = TracePerfParams; std::vector

gTestsWithID = CombineWithValues({P()}, AllEnums(), CombineTestID); -std::vector

gTestsWithRenderer = CombineWithFuncs(gTestsWithID, {Vulkan

}); +std::vector

gTestsWithRenderer = CombineWithFuncs(gTestsWithID, {Vulkan

, EGL

}); ANGLE_INSTANTIATE_TEST_ARRAY(TracePerfTest, gTestsWithRenderer); } // anonymous namespace diff --git a/src/tests/test_utils/ANGLETest.cpp b/src/tests/test_utils/ANGLETest.cpp index a2bcb6019..129fa001b 100644 --- a/src/tests/test_utils/ANGLETest.cpp +++ b/src/tests/test_utils/ANGLETest.cpp @@ -279,11 +279,11 @@ GLColor32F ReadColor32F(GLint x, GLint y) return actual; } -void LoadEntryPointsWithUtilLoader() +void LoadEntryPointsWithUtilLoader(angle::GLESDriverType driverType) { #if defined(ANGLE_USE_UTIL_LOADER) PFNEGLGETPROCADDRESSPROC getProcAddress; - ANGLETestEnvironment::GetEGLLibrary()->getAs("eglGetProcAddress", &getProcAddress); + ANGLETestEnvironment::GetDriverLibrary(driverType)->getAs("eglGetProcAddress", &getProcAddress); ASSERT_NE(nullptr, getProcAddress); LoadEGL(getProcAddress); @@ -454,18 +454,13 @@ void ANGLETestBase::initOSWindow() switch (mCurrentParams->driver) { case GLESDriverType::AngleEGL: + case GLESDriverType::SystemEGL: { mFixture->eglWindow = EGLWindow::New(mCurrentParams->majorVersion, mCurrentParams->minorVersion); break; } - case GLESDriverType::SystemEGL: - { - std::cerr << "Unsupported driver." << std::endl; - break; - } - case GLESDriverType::SystemWGL: { // WGL tests are currently disabled. @@ -536,10 +531,16 @@ void ANGLETestBase::ANGLETestSetUp() if (mCurrentParams->noFixture) { - LoadEntryPointsWithUtilLoader(); + LoadEntryPointsWithUtilLoader(mCurrentParams->driver); return; } + if (mLastLoadedDriver.valid() && mCurrentParams->driver != mLastLoadedDriver.value()) + { + LoadEntryPointsWithUtilLoader(mCurrentParams->driver); + mLastLoadedDriver = mCurrentParams->driver; + } + // Resize the window before creating the context so that the first make current // sets the viewport and scissor box to the right size. bool needSwap = false; @@ -559,11 +560,13 @@ void ANGLETestBase::ANGLETestSetUp() } else { + Library *driverLib = ANGLETestEnvironment::GetDriverLibrary(mCurrentParams->driver); + if (mForceNewDisplay || !mFixture->eglWindow->isDisplayInitialized()) { mFixture->eglWindow->destroyGL(); - if (!mFixture->eglWindow->initializeDisplay(mFixture->osWindow, - ANGLETestEnvironment::GetEGLLibrary(), + if (!mFixture->eglWindow->initializeDisplay(mFixture->osWindow, driverLib, + mCurrentParams->driver, mCurrentParams->eglParameters)) { FAIL() << "EGL Display init failed."; @@ -574,8 +577,8 @@ void ANGLETestBase::ANGLETestSetUp() FAIL() << "Internal parameter conflict error."; } - if (!mFixture->eglWindow->initializeSurface( - mFixture->osWindow, ANGLETestEnvironment::GetEGLLibrary(), mFixture->configParams)) + if (!mFixture->eglWindow->initializeSurface(mFixture->osWindow, driverLib, + mFixture->configParams)) { FAIL() << "egl surface init failed."; } @@ -1286,9 +1289,11 @@ ANGLETestBase::ScopedIgnorePlatformMessages::~ScopedIgnorePlatformMessages() OSWindow *ANGLETestBase::mOSWindowSingleton = nullptr; std::map ANGLETestBase::gFixtures; Optional ANGLETestBase::mLastRendererType; +Optional ANGLETestBase::mLastLoadedDriver; -std::unique_ptr ANGLETestEnvironment::gEGLLibrary; -std::unique_ptr ANGLETestEnvironment::gWGLLibrary; +std::unique_ptr ANGLETestEnvironment::gAngleEGLLibrary; +std::unique_ptr ANGLETestEnvironment::gSystemEGLLibrary; +std::unique_ptr ANGLETestEnvironment::gSystemWGLLibrary; void ANGLETestEnvironment::SetUp() {} @@ -1297,26 +1302,58 @@ void ANGLETestEnvironment::TearDown() ANGLETestBase::ReleaseFixtures(); } -Library *ANGLETestEnvironment::GetEGLLibrary() +// static +Library *ANGLETestEnvironment::GetDriverLibrary(angle::GLESDriverType driver) { -#if defined(ANGLE_USE_UTIL_LOADER) - if (!gEGLLibrary) + switch (driver) { - gEGLLibrary.reset(OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, SearchType::ApplicationDir)); + case angle::GLESDriverType::AngleEGL: + return GetAngleEGLLibrary(); + case angle::GLESDriverType::SystemEGL: + return GetSystemEGLLibrary(); + case angle::GLESDriverType::SystemWGL: + return GetSystemWGLLibrary(); + default: + return nullptr; } -#endif // defined(ANGLE_USE_UTIL_LOADER) - return gEGLLibrary.get(); } -Library *ANGLETestEnvironment::GetWGLLibrary() +// static +Library *ANGLETestEnvironment::GetAngleEGLLibrary() +{ +#if defined(ANGLE_USE_UTIL_LOADER) + if (!gAngleEGLLibrary) + { + gAngleEGLLibrary.reset( + OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, SearchType::ApplicationDir)); + } +#endif // defined(ANGLE_USE_UTIL_LOADER) + return gAngleEGLLibrary.get(); +} + +// static +Library *ANGLETestEnvironment::GetSystemEGLLibrary() +{ +#if defined(ANGLE_USE_UTIL_LOADER) + if (!gSystemEGLLibrary) + { + gSystemEGLLibrary.reset( + OpenSharedLibraryWithExtension(GetNativeEGLLibraryNameWithExtension())); + } +#endif // defined(ANGLE_USE_UTIL_LOADER) + return gSystemEGLLibrary.get(); +} + +// static +Library *ANGLETestEnvironment::GetSystemWGLLibrary() { #if defined(ANGLE_USE_UTIL_LOADER) && defined(ANGLE_PLATFORM_WINDOWS) - if (!gWGLLibrary) + if (!gSystemWGLLibrary) { - gWGLLibrary.reset(OpenSharedLibrary("opengl32", SearchType::SystemDir)); + gSystemWGLLibrary.reset(OpenSharedLibrary("opengl32", SearchType::SystemDir)); } #endif // defined(ANGLE_USE_UTIL_LOADER) && defined(ANGLE_PLATFORM_WINDOWS) - return gWGLLibrary.get(); + return gSystemWGLLibrary.get(); } void ANGLEProcessTestArgs(int *argc, char *argv[]) diff --git a/src/tests/test_utils/ANGLETest.h b/src/tests/test_utils/ANGLETest.h index 8e1c46649..06df0cfa0 100644 --- a/src/tests/test_utils/ANGLETest.h +++ b/src/tests/test_utils/ANGLETest.h @@ -186,7 +186,7 @@ constexpr std::array kCubeFaces = { GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z}}; -void LoadEntryPointsWithUtilLoader(); +void LoadEntryPointsWithUtilLoader(angle::GLESDriverType driver); } // namespace angle @@ -545,6 +545,7 @@ class ANGLETestBase // Workaround for NVIDIA not being able to share a window with OpenGL and Vulkan. static Optional mLastRendererType; + static Optional mLastLoadedDriver; }; template @@ -596,13 +597,17 @@ class ANGLETestEnvironment : public testing::Environment void SetUp() override; void TearDown() override; - static angle::Library *GetEGLLibrary(); - static angle::Library *GetWGLLibrary(); + static angle::Library *GetDriverLibrary(angle::GLESDriverType driver); private: + static angle::Library *GetAngleEGLLibrary(); + static angle::Library *GetSystemEGLLibrary(); + static angle::Library *GetSystemWGLLibrary(); + // For loading entry points. - static std::unique_ptr gEGLLibrary; - static std::unique_ptr gWGLLibrary; + static std::unique_ptr gAngleEGLLibrary; + static std::unique_ptr gSystemEGLLibrary; + static std::unique_ptr gSystemWGLLibrary; }; extern angle::PlatformMethods gDefaultPlatformMethods; diff --git a/src/tests/test_utils/angle_test_configs.cpp b/src/tests/test_utils/angle_test_configs.cpp index b04ea173f..d37bfcd7a 100644 --- a/src/tests/test_utils/angle_test_configs.cpp +++ b/src/tests/test_utils/angle_test_configs.cpp @@ -112,7 +112,7 @@ std::ostream &operator<<(std::ostream &stream, const PlatformParameters &pp) stream << "WGL"; break; case GLESDriverType::SystemEGL: - stream << "GLES"; + stream << "EGL"; break; default: stream << "Error"; @@ -769,4 +769,28 @@ PlatformParameters ES3_WGL() { return PlatformParameters(3, 0, GLESDriverType::SystemWGL); } + +PlatformParameters ES2_EGL() +{ + return PlatformParameters(2, 0, GLESDriverType::SystemEGL); +} + +PlatformParameters ES3_EGL() +{ + return PlatformParameters(3, 0, GLESDriverType::SystemEGL); +} + +const char *GetNativeEGLLibraryNameWithExtension() +{ +#if defined(ANGLE_PLATFORM_ANDROID) + return "libEGL.so"; +#elif defined(ANGLE_PLATFORM_LINUX) + return "libEGL.so.1"; +#elif defined(ANGLE_PLATFORM_WINDOWS) + return "libEGL.dll"; +#else + return "unknown_libegl"; +#endif +} + } // namespace angle diff --git a/src/tests/test_utils/angle_test_configs.h b/src/tests/test_utils/angle_test_configs.h index 5f7713896..c6d446075 100644 --- a/src/tests/test_utils/angle_test_configs.h +++ b/src/tests/test_utils/angle_test_configs.h @@ -23,17 +23,6 @@ namespace angle { -// The GLES driver type determines what shared object we use to load the GLES entry points. -// AngleEGL loads from ANGLE's version of libEGL, libGLESv2, and libGLESv1_CM. -// SystemEGL uses the system copies of libEGL, libGLESv2, and libGLESv1_CM. -// SystemWGL loads Windows GL with the GLES compatiblity extensions. See util/WGLWindow.h. -enum class GLESDriverType -{ - AngleEGL, - SystemEGL, - SystemWGL, -}; - struct PlatformParameters { PlatformParameters(); @@ -197,6 +186,11 @@ PlatformParameters ES3_METAL(); PlatformParameters ES2_WGL(); PlatformParameters ES3_WGL(); +PlatformParameters ES2_EGL(); +PlatformParameters ES3_EGL(); + +const char *GetNativeEGLLibraryNameWithExtension(); + inline PlatformParameters WithNoVirtualContexts(const PlatformParameters ¶ms) { PlatformParameters withNoVirtualContexts = params; diff --git a/src/tests/test_utils/angle_test_instantiate.cpp b/src/tests/test_utils/angle_test_instantiate.cpp index a394d08ce..27c80ab0e 100644 --- a/src/tests/test_utils/angle_test_instantiate.cpp +++ b/src/tests/test_utils/angle_test_instantiate.cpp @@ -14,6 +14,7 @@ #include #include "angle_gl.h" +#include "common/debug.h" #include "common/platform.h" #include "common/system_utils.h" #include "common/third_party/base/anglebase/no_destructor.h" @@ -36,7 +37,7 @@ namespace angle { namespace { -bool IsANGLEConfigSupported(const PlatformParameters ¶m, OSWindow *osWindow) +bool IsAngleEGLConfigSupported(const PlatformParameters ¶m, OSWindow *osWindow) { std::unique_ptr eglLibrary; @@ -48,13 +49,14 @@ bool IsANGLEConfigSupported(const PlatformParameters ¶m, OSWindow *osWindow) EGLWindow *eglWindow = EGLWindow::New(param.majorVersion, param.minorVersion); ConfigParameters configParams; bool result = - eglWindow->initializeGL(osWindow, eglLibrary.get(), param.eglParameters, configParams); + eglWindow->initializeGL(osWindow, eglLibrary.get(), angle::GLESDriverType::AngleEGL, + param.eglParameters, configParams); eglWindow->destroyGL(); EGLWindow::Delete(&eglWindow); return result; } -bool IsWGLConfigSupported(const PlatformParameters ¶m, OSWindow *osWindow) +bool IsSystemWGLConfigSupported(const PlatformParameters ¶m, OSWindow *osWindow) { #if defined(ANGLE_PLATFORM_WINDOWS) && defined(ANGLE_USE_UTIL_LOADER) std::unique_ptr openglLibrary( @@ -63,7 +65,8 @@ bool IsWGLConfigSupported(const PlatformParameters ¶m, OSWindow *osWindow) WGLWindow *wglWindow = WGLWindow::New(param.majorVersion, param.minorVersion); ConfigParameters configParams; bool result = - wglWindow->initializeGL(osWindow, openglLibrary.get(), param.eglParameters, configParams); + wglWindow->initializeGL(osWindow, openglLibrary.get(), angle::GLESDriverType::SystemWGL, + param.eglParameters, configParams); wglWindow->destroyGL(); WGLWindow::Delete(&wglWindow); return result; @@ -72,10 +75,24 @@ bool IsWGLConfigSupported(const PlatformParameters ¶m, OSWindow *osWindow) #endif // defined(ANGLE_PLATFORM_WINDOWS) && defined(ANGLE_USE_UTIL_LOADER) } -bool IsNativeConfigSupported(const PlatformParameters ¶m, OSWindow *osWindow) +bool IsSystemEGLConfigSupported(const PlatformParameters ¶m, OSWindow *osWindow) { - // Not yet implemented. +#if defined(ANGLE_USE_UTIL_LOADER) + std::unique_ptr eglLibrary; + + eglLibrary.reset(OpenSharedLibraryWithExtension(GetNativeEGLLibraryNameWithExtension())); + + EGLWindow *eglWindow = EGLWindow::New(param.majorVersion, param.minorVersion); + ConfigParameters configParams; + bool result = + eglWindow->initializeGL(osWindow, eglLibrary.get(), angle::GLESDriverType::SystemEGL, + param.eglParameters, configParams); + eglWindow->destroyGL(); + EGLWindow::Delete(&eglWindow); + return result; +#else return false; +#endif } bool IsAndroidDevice(const std::string &deviceName) @@ -412,13 +429,23 @@ bool IsConfigWhitelisted(const SystemInfo &systemInfo, const PlatformParameters return (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE); } + if (IsLinux() || IsAndroid()) + { + // We do not support WGL bindings on Linux/Android. We do support system EGL. + switch (param.driver) + { + case GLESDriverType::SystemEGL: + return param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; + case GLESDriverType::SystemWGL: + return false; + default: + break; + } + } + if (IsLinux()) { - // We do not support non-ANGLE bindings on Linux. - if (param.driver != GLESDriverType::AngleEGL) - { - return false; - } + ASSERT(param.driver == GLESDriverType::AngleEGL); // Currently we support the OpenGL and Vulkan back-ends on Linux. switch (param.getRenderer()) @@ -434,11 +461,7 @@ bool IsConfigWhitelisted(const SystemInfo &systemInfo, const PlatformParameters if (IsAndroid()) { - // We do not support non-ANGLE bindings on Android. - if (param.driver != GLESDriverType::AngleEGL) - { - return false; - } + ASSERT(param.driver == GLESDriverType::AngleEGL); // Nexus Android devices don't support backing 3.2 contexts if (param.eglParameters.majorVersion == 3 && param.eglParameters.minorVersion == 2) @@ -493,13 +516,13 @@ bool IsConfigSupported(const PlatformParameters ¶m) switch (param.driver) { case GLESDriverType::AngleEGL: - result = IsANGLEConfigSupported(param, osWindow); + result = IsAngleEGLConfigSupported(param, osWindow); break; case GLESDriverType::SystemEGL: - result = IsNativeConfigSupported(param, osWindow); + result = IsSystemEGLConfigSupported(param, osWindow); break; case GLESDriverType::SystemWGL: - result = IsWGLConfigSupported(param, osWindow); + result = IsSystemWGLConfigSupported(param, osWindow); break; } diff --git a/util/EGLPlatformParameters.h b/util/EGLPlatformParameters.h index f55366748..9122367ca 100644 --- a/util/EGLPlatformParameters.h +++ b/util/EGLPlatformParameters.h @@ -15,6 +15,17 @@ namespace angle { struct PlatformMethods; + +// The GLES driver type determines what shared object we use to load the GLES entry points. +// AngleEGL loads from ANGLE's version of libEGL, libGLESv2, and libGLESv1_CM. +// SystemEGL uses the system copies of libEGL, libGLESv2, and libGLESv1_CM. +// SystemWGL loads Windows GL with the GLES compatiblity extensions. See util/WGLWindow.h. +enum class GLESDriverType +{ + AngleEGL, + SystemEGL, + SystemWGL, +}; } // namespace angle struct EGLPlatformParameters diff --git a/util/EGLWindow.cpp b/util/EGLWindow.cpp index af5d1aaef..c257290df 100644 --- a/util/EGLWindow.cpp +++ b/util/EGLWindow.cpp @@ -92,10 +92,11 @@ EGLContext EGLWindow::getContext() const bool EGLWindow::initializeGL(OSWindow *osWindow, angle::Library *glWindowingLibrary, + angle::GLESDriverType driverType, const EGLPlatformParameters &platformParams, const ConfigParameters &configParams) { - if (!initializeDisplay(osWindow, glWindowingLibrary, platformParams)) + if (!initializeDisplay(osWindow, glWindowingLibrary, driverType, platformParams)) return false; if (!initializeSurface(osWindow, glWindowingLibrary, configParams)) return false; @@ -106,6 +107,7 @@ bool EGLWindow::initializeGL(OSWindow *osWindow, bool EGLWindow::initializeDisplay(OSWindow *osWindow, angle::Library *glWindowingLibrary, + angle::GLESDriverType driverType, const EGLPlatformParameters ¶ms) { #if defined(ANGLE_USE_UTIL_LOADER) @@ -113,6 +115,7 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow, glWindowingLibrary->getAs("eglGetProcAddress", &getProcAddress); if (!getProcAddress) { + fprintf(stderr, "Cannot load eglGetProcAddress\n"); return false; } @@ -192,7 +195,7 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow, { if (strstr(extensionString, "EGL_ANGLE_feature_control") == nullptr) { - std::cout << "Missing EGL_ANGLE_feature_control.\n"; + fprintf(stderr, "Missing EGL_ANGLE_feature_control.\n"); destroyGL(); return false; } @@ -207,7 +210,7 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow, { if (strstr(extensionString, "EGL_ANGLE_feature_control") == nullptr) { - std::cout << "Missing EGL_ANGLE_feature_control.\n"; + fprintf(stderr, "Missing EGL_ANGLE_feature_control.\n"); destroyGL(); return false; } @@ -220,17 +223,31 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow, displayAttributes.push_back(EGL_NONE); - mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, - reinterpret_cast(osWindow->getNativeDisplay()), - &displayAttributes[0]); + if (driverType == angle::GLESDriverType::SystemWGL) + return false; + + if (driverType == angle::GLESDriverType::AngleEGL && + strstr(extensionString, "EGL_ANGLE_platform_angle")) + { + mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, + reinterpret_cast(osWindow->getNativeDisplay()), + &displayAttributes[0]); + } + else + { + mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + } + if (mDisplay == EGL_NO_DISPLAY) { + fprintf(stderr, "Failed to get display: 0x%X\n", eglGetError()); destroyGL(); return false; } if (eglInitialize(mDisplay, &mEGLMajorVersion, &mEGLMinorVersion) == EGL_FALSE) { + fprintf(stderr, "eglInitialize failed: 0x%X\n", eglGetError()); destroyGL(); return false; } @@ -269,6 +286,7 @@ bool EGLWindow::initializeSurface(OSWindow *osWindow, bool hasPixelFormatFloat = strstr(displayExtensions, "EGL_EXT_pixel_format_float") != nullptr; if (!hasPixelFormatFloat && mConfigParams.componentType != EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { + fprintf(stderr, "Mising EGL_EXT_pixel_format_float.\n"); destroyGL(); return false; } @@ -283,7 +301,7 @@ bool EGLWindow::initializeSurface(OSWindow *osWindow, if (!FindEGLConfig(mDisplay, configAttributes.data(), &mConfig)) { - std::cout << "Could not find a suitable EGL config!" << std::endl; + fprintf(stderr, "Could not find a suitable EGL config!\n"); destroyGL(); return false; } @@ -320,6 +338,7 @@ bool EGLWindow::initializeSurface(OSWindow *osWindow, &surfaceAttributes[0]); if (eglGetError() != EGL_SUCCESS || (mSurface == EGL_NO_SURFACE)) { + fprintf(stderr, "eglCreateWindowSurface failed: 0x%X\n", eglGetError()); destroyGL(); return false; } @@ -340,7 +359,7 @@ EGLContext EGLWindow::createContext(EGLContext share) const if (mClientMajorVersion > 2 && !(mEGLMajorVersion > 1 || mEGLMinorVersion >= 5) && !hasKHRCreateContext) { - std::cerr << "EGL_KHR_create_context incompatibility.\n"; + fprintf(stderr, "EGL_KHR_create_context incompatibility.\n"); return EGL_NO_CONTEXT; } @@ -348,7 +367,7 @@ EGLContext EGLWindow::createContext(EGLContext share) const bool hasDebug = mEGLMinorVersion >= 5; if (mConfigParams.debug && !hasDebug) { - std::cerr << "EGL 1.5 is required for EGL_CONTEXT_OPENGL_DEBUG.\n"; + fprintf(stderr, "EGL 1.5 is required for EGL_CONTEXT_OPENGL_DEBUG.\n"); return EGL_NO_CONTEXT; } @@ -356,7 +375,7 @@ EGLContext EGLWindow::createContext(EGLContext share) const strstr(displayExtensions, "EGL_ANGLE_create_context_webgl_compatibility") != nullptr; if (mConfigParams.webGLCompatibility.valid() && !hasWebGLCompatibility) { - std::cerr << "EGL_ANGLE_create_context_webgl_compatibility missing.\n"; + fprintf(stderr, "EGL_ANGLE_create_context_webgl_compatibility missing.\n"); return EGL_NO_CONTEXT; } @@ -364,7 +383,7 @@ EGLContext EGLWindow::createContext(EGLContext share) const strstr(displayExtensions, "EGL_ANGLE_create_context_extensions_enabled") != nullptr; if (mConfigParams.extensionsEnabled.valid() && !hasCreateContextExtensionsEnabled) { - std::cerr << "EGL_ANGLE_create_context_extensions_enabled missing.\n"; + fprintf(stderr, "EGL_ANGLE_create_context_extensions_enabled missing.\n"); return EGL_NO_CONTEXT; } @@ -373,7 +392,7 @@ EGLContext EGLWindow::createContext(EGLContext share) const mConfigParams.resetStrategy != EGL_NO_RESET_NOTIFICATION_EXT) && !hasRobustness) { - std::cerr << "EGL_EXT_create_context_robustness missing.\n"; + fprintf(stderr, "EGL_EXT_create_context_robustness missing.\n"); return EGL_NO_CONTEXT; } @@ -381,7 +400,7 @@ EGLContext EGLWindow::createContext(EGLContext share) const strstr(displayExtensions, "EGL_CHROMIUM_create_context_bind_generates_resource") != nullptr; if (!mConfigParams.bindGeneratesResource && !hasBindGeneratesResource) { - std::cerr << "EGL_CHROMIUM_create_context_bind_generates_resource missing.\n"; + fprintf(stderr, "EGL_CHROMIUM_create_context_bind_generates_resource missing.\n"); return EGL_NO_CONTEXT; } @@ -390,7 +409,7 @@ EGLContext EGLWindow::createContext(EGLContext share) const if (!mConfigParams.clientArraysEnabled && !hasClientArraysExtension) { // Non-default state requested without the extension present - std::cerr << "EGL_ANGLE_create_context_client_arrays missing.\n"; + fprintf(stderr, "EGL_ANGLE_create_context_client_arrays missing.\n"); return EGL_NO_CONTEXT; } @@ -398,7 +417,7 @@ EGLContext EGLWindow::createContext(EGLContext share) const strstr(displayExtensions, "EGL_ANGLE_program_cache_control ") != nullptr; if (mConfigParams.contextProgramCacheEnabled.valid() && !hasProgramCacheControlExtension) { - std::cerr << "EGL_ANGLE_program_cache_control missing.\n"; + fprintf(stderr, "EGL_ANGLE_program_cache_control missing.\n"); return EGL_NO_CONTEXT; } @@ -406,14 +425,14 @@ EGLContext EGLWindow::createContext(EGLContext share) const strstr(displayExtensions, "EGL_KHR_create_context_no_error") != nullptr; if (mConfigParams.noError && !hasKHRCreateContextNoError) { - std::cerr << "EGL_KHR_create_context_no_error missing.\n"; + fprintf(stderr, "EGL_KHR_create_context_no_error missing.\n"); return EGL_NO_CONTEXT; } eglBindAPI(EGL_OPENGL_ES_API); if (eglGetError() != EGL_SUCCESS) { - std::cerr << "Error on eglBindAPI.\n"; + fprintf(stderr, "Error on eglBindAPI.\n"); return EGL_NO_CONTEXT; } @@ -426,7 +445,9 @@ EGLContext EGLWindow::createContext(EGLContext share) const contextAttributes.push_back(EGL_CONTEXT_MINOR_VERSION_KHR); contextAttributes.push_back(mClientMinorVersion); - if (hasDebug) + // Note that the Android loader currently doesn't handle this flag despite reporting 1.5. + // Work around this by only using the debug bit when we request a debug context. + if (hasDebug && mConfigParams.debug) { contextAttributes.push_back(EGL_CONTEXT_OPENGL_DEBUG); contextAttributes.push_back(mConfigParams.debug ? EGL_TRUE : EGL_FALSE); @@ -501,9 +522,9 @@ EGLContext EGLWindow::createContext(EGLContext share) const contextAttributes.push_back(EGL_NONE); EGLContext context = eglCreateContext(mDisplay, mConfig, share, &contextAttributes[0]); - if (eglGetError() != EGL_SUCCESS) + if (context == EGL_NO_CONTEXT) { - std::cerr << "Error on eglCreateContext.\n"; + fprintf(stderr, "eglCreateContext failed: 0x%X\n", eglGetError()); return EGL_NO_CONTEXT; } @@ -611,7 +632,7 @@ bool EGLWindow::makeCurrent() if (eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) == EGL_FALSE || eglGetError() != EGL_SUCCESS) { - std::cerr << "Error during eglMakeCurrent.\n"; + fprintf(stderr, "Error during eglMakeCurrent.\n"); return false; } @@ -622,7 +643,7 @@ bool EGLWindow::setSwapInterval(EGLint swapInterval) { if (eglSwapInterval(mDisplay, swapInterval) == EGL_FALSE || eglGetError() != EGL_SUCCESS) { - std::cerr << "Error during eglSwapInterval.\n"; + fprintf(stderr, "Error during eglSwapInterval.\n"); return false; } diff --git a/util/EGLWindow.h b/util/EGLWindow.h index cc1402f41..adab5151f 100644 --- a/util/EGLWindow.h +++ b/util/EGLWindow.h @@ -69,6 +69,7 @@ class ANGLE_UTIL_EXPORT GLWindowBase : angle::NonCopyable virtual bool initializeGL(OSWindow *osWindow, angle::Library *glWindowingLibrary, + angle::GLESDriverType driverType, const EGLPlatformParameters &platformParams, const ConfigParameters &configParams) = 0; virtual bool isGLInitialized() const = 0; @@ -112,6 +113,7 @@ class ANGLE_UTIL_EXPORT EGLWindow : public GLWindowBase // Internally initializes the Display, Surface and Context. bool initializeGL(OSWindow *osWindow, angle::Library *glWindowingLibrary, + angle::GLESDriverType driverType, const EGLPlatformParameters &platformParams, const ConfigParameters &configParams) override; @@ -125,6 +127,7 @@ class ANGLE_UTIL_EXPORT EGLWindow : public GLWindowBase // Only initializes the Display. bool initializeDisplay(OSWindow *osWindow, angle::Library *glWindowingLibrary, + angle::GLESDriverType driverType, const EGLPlatformParameters ¶ms); // Only initializes the Surface. diff --git a/util/windows/WGLWindow.cpp b/util/windows/WGLWindow.cpp index a9e82e15c..68edea5e3 100644 --- a/util/windows/WGLWindow.cpp +++ b/util/windows/WGLWindow.cpp @@ -71,9 +71,15 @@ WGLWindow::~WGLWindow() {} // Internally initializes GL resources. bool WGLWindow::initializeGL(OSWindow *osWindow, angle::Library *glWindowingLibrary, + angle::GLESDriverType driverType, const EGLPlatformParameters &platformParams, const ConfigParameters &configParams) { + if (driverType != angle::GLESDriverType::SystemWGL) + { + return false; + } + glWindowingLibrary->getAs("wglGetProcAddress", &gCurrentWGLGetProcAddress); if (!gCurrentWGLGetProcAddress) diff --git a/util/windows/WGLWindow.h b/util/windows/WGLWindow.h index a614bb35e..5ecc562e4 100644 --- a/util/windows/WGLWindow.h +++ b/util/windows/WGLWindow.h @@ -30,6 +30,7 @@ class ANGLE_UTIL_EXPORT WGLWindow : public GLWindowBase // Internally initializes GL resources. bool initializeGL(OSWindow *osWindow, angle::Library *glWindowingLibrary, + angle::GLESDriverType driverType, const EGLPlatformParameters &platformParams, const ConfigParameters &configParams) override; void destroyGL() override;