From 6a02f06dfd4ec5e0f9efb553059ce65535f4b312 Mon Sep 17 00:00:00 2001 From: Geoff Lang Date: Thu, 18 Jul 2019 16:27:14 -0400 Subject: [PATCH] Implement EGL_ANGLE_create_context_backwards_compatible This extension allows the user to specify if ANGLE should create a context of the exact requested version or a higher version context that is backwards compatible. BUG=angleproject:3425 Change-Id: I7d0b75cdd7e34a2fc888aa238e1eeb67af82ae0d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1601560 Commit-Queue: Geoff Lang Reviewed-by: Shahbaz Youssefi --- BUILD.gn | 3 - ...LE_create_context_backwards_compatible.txt | 93 ++++++++++ gni/angle.gni | 3 - include/EGL/eglext_angle.h | 5 + src/libANGLE/Caps.cpp | 1 + src/libANGLE/Caps.h | 3 + src/libANGLE/Context.cpp | 39 +++- src/libANGLE/Context.h | 2 +- src/libANGLE/Display.cpp | 7 +- src/libANGLE/renderer/DisplayImpl.h | 1 + src/libANGLE/renderer/d3d/DisplayD3D.cpp | 5 + src/libANGLE/renderer/d3d/DisplayD3D.h | 1 + src/libANGLE/renderer/d3d/RendererD3D.h | 1 + .../renderer/d3d/d3d11/Renderer11.cpp | 6 + src/libANGLE/renderer/d3d/d3d11/Renderer11.h | 1 + src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp | 5 + src/libANGLE/renderer/d3d/d3d9/Renderer9.h | 1 + src/libANGLE/renderer/gl/DisplayGL.cpp | 6 + src/libANGLE/renderer/gl/DisplayGL.h | 2 + src/libANGLE/renderer/null/DisplayNULL.cpp | 5 + src/libANGLE/renderer/null/DisplayNULL.h | 1 + src/libANGLE/renderer/vulkan/DisplayVk.cpp | 5 + src/libANGLE/renderer/vulkan/DisplayVk.h | 1 + src/libANGLE/renderer/vulkan/RendererVk.cpp | 11 +- src/libANGLE/renderer/vulkan/RendererVk.h | 1 + src/libANGLE/validationEGL.cpp | 15 ++ src/tests/angle_end2end_tests.gni | 1 + .../EGLBackwardsCompatibleContextTest.cpp | 166 ++++++++++++++++++ src/tests/egl_tests/EGLQueryContextTest.cpp | 2 +- .../test_utils/angle_test_instantiate.cpp | 8 - util/EGLWindow.cpp | 15 ++ 31 files changed, 386 insertions(+), 30 deletions(-) create mode 100644 extensions/EGL_ANGLE_create_context_backwards_compatible.txt create mode 100644 src/tests/egl_tests/EGLBackwardsCompatibleContextTest.cpp diff --git a/BUILD.gn b/BUILD.gn index e2c639837ea..2f3fd72d1fa 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -96,9 +96,6 @@ config("internal_config") { if (angle_enable_vulkan_gpu_trace_events) { defines += [ "ANGLE_ENABLE_VULKAN_GPU_TRACE_EVENTS=1" ] } - if (angle_vulkan_conformant_configs_only) { - defines += [ "ANGLE_VULKAN_CONFORMANT_CONFIGS_ONLY=1" ] - } } if (angle_enable_trace) { diff --git a/extensions/EGL_ANGLE_create_context_backwards_compatible.txt b/extensions/EGL_ANGLE_create_context_backwards_compatible.txt new file mode 100644 index 00000000000..21e319a7101 --- /dev/null +++ b/extensions/EGL_ANGLE_create_context_backwards_compatible.txt @@ -0,0 +1,93 @@ +Name + + ANGLE_create_context_backwards_compatible + +Name Strings + + EGL_ANGLE_create_context_backwards_compatible + +Contributors + + Geoff Lang + +Contacts + + Geoff Lang (geofflang 'at' google.com) + +Status + + Draft + +Version + + Version 1, May 8, 2019 + +Number + + EGL Extension #?? + +Dependencies + + Requires EGL 1.4. + + Written against the EGL 1.5 specification. + +Overview + + This extension allows the user to create a context with exact major and + minor versions. By default, a context may be created of any version that + is backwards-compatible with the requested verion but it is often useful to + users to request and target a specific version. + +New Types + + None + +New Procedures and Functions + + None + +New Tokens + + Accepted as an attribute name in the <*attrib_list> argument to + eglCreateContext: + + EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE 0x3483 + +Additions to the EGL 1.5 Specification + + Modify section 3.7.1.1 "OpenGL and OpenGL ES Context Versions": + + - The context returned must be the specified version, or a later version + - which is backwards compatible with that version. + + + The context returned must be the specified version, or a later version + + which is backwards compatible with that version if + + EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE is EGL_TRUE. + + Append to section 3.7.1.1 "OpenGL and OpenGL ES Context Versions": + + The default value of EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE is + EGL_TRUE. + +Errors + + None + +New State + + None + +Conformance Tests + + TBD + +Issues + + None + +Revision History + + Rev. Date Author Changes + ---- ------------- --------- ---------------------------------------- + 1 May 8, 2019 geofflang Initial version diff --git a/gni/angle.gni b/gni/angle.gni index 1bcb973ad37..0fb022fd12f 100644 --- a/gni/angle.gni +++ b/gni/angle.gni @@ -85,9 +85,6 @@ declare_args() { # Enable Vulkan GPU trace event capability angle_enable_vulkan_gpu_trace_events = false - # Disallow non-conformant configurations in official builds. - angle_vulkan_conformant_configs_only = is_official_build - # Enable custom (cpu-side) secondary command buffers angle_enable_custom_vulkan_cmd_buffers = true } diff --git a/include/EGL/eglext_angle.h b/include/EGL/eglext_angle.h index 1af599eee9b..382a3598baf 100644 --- a/include/EGL/eglext_angle.h +++ b/include/EGL/eglext_angle.h @@ -231,6 +231,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribANGLE(EGLDisplay dpy, EGLint #define EGL_D3D11_TEXTURE_ANGLE 0x3484 #endif /* EGL_ANGLE_image_d3d11_texture */ +#ifndef EGL_ANGLE_create_context_backwards_compatible +#define EGL_ANGLE_create_context_backwards_compatible 1 +#define EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE 0x3483 +#endif /* EGL_ANGLE_create_context_backwards_compatible */ + // clang-format on #endif // INCLUDE_EGL_EGLEXT_ANGLE_ diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp index 8c78f7f90a6..3d1930193e1 100644 --- a/src/libANGLE/Caps.cpp +++ b/src/libANGLE/Caps.cpp @@ -1188,6 +1188,7 @@ std::vector DisplayExtensions::getStrings() const InsertExtensionString("EGL_ANGLE_image_d3d11_texture", imageD3D11Texture, &extensionStrings); InsertExtensionString("EGL_ANDROID_get_native_client_buffer", getNativeClientBufferANDROID, &extensionStrings); InsertExtensionString("EGL_ANDROID_native_fence_sync", nativeFenceSyncANDROID, &extensionStrings); + InsertExtensionString("EGL_ANGLE_create_context_backwards_compatible", createContextBackwardsCompatible, &extensionStrings); // TODO(jmadill): Enable this when complete. //InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings); // clang-format on diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h index 8e013c711fd..c727590cb91 100644 --- a/src/libANGLE/Caps.h +++ b/src/libANGLE/Caps.h @@ -913,6 +913,9 @@ struct DisplayExtensions // EGL_ANDROID_native_fence_sync bool nativeFenceSyncANDROID = false; + + // EGL_ANGLE_create_context_backwards_compatible + bool createContextBackwardsCompatible = false; }; struct DeviceExtensions diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp index 499d1c096b9..54d865e2706 100644 --- a/src/libANGLE/Context.cpp +++ b/src/libANGLE/Context.cpp @@ -42,8 +42,7 @@ #include "libANGLE/formatutils.h" #include "libANGLE/queryconversions.h" #include "libANGLE/queryutils.h" -#include "libANGLE/renderer/BufferImpl.h" -#include "libANGLE/renderer/EGLImplFactory.h" +#include "libANGLE/renderer/DisplayImpl.h" #include "libANGLE/renderer/Format.h" #include "libANGLE/validationES.h" @@ -143,9 +142,34 @@ EGLint GetClientMinorVersion(const egl::AttributeMap &attribs) return static_cast(attribs.get(EGL_CONTEXT_MINOR_VERSION, 0)); } -Version GetClientVersion(const egl::AttributeMap &attribs) +bool GetBackwardCompatibleContext(const egl::AttributeMap &attribs) { - return Version(GetClientMajorVersion(attribs), GetClientMinorVersion(attribs)); + return attribs.get(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_TRUE) == EGL_TRUE; +} + +Version GetClientVersion(egl::Display *display, const egl::AttributeMap &attribs) +{ + Version requestedVersion = + Version(GetClientMajorVersion(attribs), GetClientMinorVersion(attribs)); + if (GetBackwardCompatibleContext(attribs)) + { + if (requestedVersion.major == 1) + { + // If the user requests an ES1 context, we cannot return an ES 2+ context. + return Version(1, 1); + } + else + { + // Always up the version to at least the max conformant version this display supports. + // Only return a higher client version if requested. + return std::max(display->getImplementation()->getMaxConformantESVersion(), + requestedVersion); + } + } + else + { + return requestedVersion; + } } GLenum GetResetStrategy(const egl::AttributeMap &attribs) @@ -272,7 +296,7 @@ enum SubjectIndexes : angle::SubjectIndex }; } // anonymous namespace -Context::Context(rx::EGLImplFactory *implFactory, +Context::Context(egl::Display *display, const egl::Config *config, const Context *shareContext, TextureManager *shareTextures, @@ -285,7 +309,7 @@ Context::Context(rx::EGLImplFactory *implFactory, shareContext ? &shareContext->mState : nullptr, shareTextures, clientType, - GetClientVersion(attribs), + GetClientVersion(display, attribs), GetDebug(attribs), GetBindGeneratesResource(attribs), GetClientArraysEnabled(attribs), @@ -294,7 +318,8 @@ Context::Context(rx::EGLImplFactory *implFactory, mSkipValidation(GetNoError(attribs)), mDisplayTextureShareGroup(shareTextures != nullptr), mErrors(this), - mImplementation(implFactory->createContext(mState, &mErrors, config, shareContext, attribs)), + mImplementation(display->getImplementation() + ->createContext(mState, &mErrors, config, shareContext, attribs)), mLabel(nullptr), mCompiler(), mConfig(config), diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h index 30b2a71b3e2..db30ba3af6e 100644 --- a/src/libANGLE/Context.h +++ b/src/libANGLE/Context.h @@ -307,7 +307,7 @@ class StateCache final : angle::NonCopyable class Context final : public egl::LabeledObject, angle::NonCopyable, public angle::ObserverInterface { public: - Context(rx::EGLImplFactory *implFactory, + Context(egl::Display *display, const egl::Config *config, const Context *shareContext, TextureManager *shareTextures, diff --git a/src/libANGLE/Display.cpp b/src/libANGLE/Display.cpp index 75a97b0c9cd..687174b3997 100644 --- a/src/libANGLE/Display.cpp +++ b/src/libANGLE/Display.cpp @@ -940,8 +940,8 @@ Error Display::createContext(const Config *configuration, } gl::Context *context = - new gl::Context(mImplementation, configuration, shareContext, shareTextures, cachePointer, - clientType, attribs, mDisplayExtensions, GetClientExtensions()); + new gl::Context(this, configuration, shareContext, shareTextures, cachePointer, clientType, + attribs, mDisplayExtensions, GetClientExtensions()); ASSERT(context != nullptr); mContextSet.insert(context); @@ -1312,6 +1312,9 @@ void Display::initDisplayExtensions() // that ANativeWindow is not recordable. mDisplayExtensions.recordable = true; + // All backends support specific context versions + mDisplayExtensions.createContextBackwardsCompatible = true; + mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions); } diff --git a/src/libANGLE/renderer/DisplayImpl.h b/src/libANGLE/renderer/DisplayImpl.h index 321eecda1b8..06a5a7d4268 100644 --- a/src/libANGLE/renderer/DisplayImpl.h +++ b/src/libANGLE/renderer/DisplayImpl.h @@ -86,6 +86,7 @@ class DisplayImpl : public EGLImplFactory virtual egl::Error waitClient(const gl::Context *context) = 0; virtual egl::Error waitNative(const gl::Context *context, EGLint engine) = 0; virtual gl::Version getMaxSupportedESVersion() const = 0; + virtual gl::Version getMaxConformantESVersion() const = 0; const egl::Caps &getCaps() const; virtual void setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get) {} diff --git a/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/libANGLE/renderer/d3d/DisplayD3D.cpp index 62ed67c4db0..1970daf62d8 100644 --- a/src/libANGLE/renderer/d3d/DisplayD3D.cpp +++ b/src/libANGLE/renderer/d3d/DisplayD3D.cpp @@ -386,6 +386,11 @@ gl::Version DisplayD3D::getMaxSupportedESVersion() const return mRenderer->getMaxSupportedESVersion(); } +gl::Version DisplayD3D::getMaxConformantESVersion() const +{ + return mRenderer->getMaxConformantESVersion(); +} + void DisplayD3D::handleResult(HRESULT hr, const char *message, const char *file, diff --git a/src/libANGLE/renderer/d3d/DisplayD3D.h b/src/libANGLE/renderer/d3d/DisplayD3D.h index 80fb4e881df..e7594dc05f3 100644 --- a/src/libANGLE/renderer/d3d/DisplayD3D.h +++ b/src/libANGLE/renderer/d3d/DisplayD3D.h @@ -83,6 +83,7 @@ class DisplayD3D : public DisplayImpl, public d3d::Context egl::Error waitClient(const gl::Context *context) override; egl::Error waitNative(const gl::Context *context, EGLint engine) override; gl::Version getMaxSupportedESVersion() const override; + gl::Version getMaxConformantESVersion() const override; void handleResult(HRESULT hr, const char *message, diff --git a/src/libANGLE/renderer/d3d/RendererD3D.h b/src/libANGLE/renderer/d3d/RendererD3D.h index 2dcd68e287f..0c54e0b8283 100644 --- a/src/libANGLE/renderer/d3d/RendererD3D.h +++ b/src/libANGLE/renderer/d3d/RendererD3D.h @@ -387,6 +387,7 @@ class RendererD3D : public BufferFactoryD3D virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0; virtual gl::Version getMaxSupportedESVersion() const = 0; + virtual gl::Version getMaxConformantESVersion() const = 0; angle::Result initRenderTarget(const gl::Context *context, RenderTargetD3D *renderTarget); diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index 3190bbc5eb8..62f263b642d 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -3702,6 +3702,12 @@ gl::Version Renderer11::getMaxSupportedESVersion() const return d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel); } +gl::Version Renderer11::getMaxConformantESVersion() const +{ + // Always force a 2.0 context unless the user explicitly requests higher + return std::min(getMaxSupportedESVersion(), gl::Version(2, 0)); +} + gl::DebugAnnotator *Renderer11::getAnnotator() { return &mAnnotator; diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h index 708b5bd4237..8016d2bfcab 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h +++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h @@ -427,6 +427,7 @@ class Renderer11 : public RendererD3D angle::MemoryBuffer **bufferOut); gl::Version getMaxSupportedESVersion() const override; + gl::Version getMaxConformantESVersion() const override; angle::Result dispatchCompute(const gl::Context *context, GLuint numGroupsX, diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp index 96f15bff7b3..558023658d5 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp @@ -3084,6 +3084,11 @@ gl::Version Renderer9::getMaxSupportedESVersion() const return gl::Version(2, 0); } +gl::Version Renderer9::getMaxConformantESVersion() const +{ + return gl::Version(2, 0); +} + angle::Result Renderer9::clearRenderTarget(const gl::Context *context, RenderTargetD3D *renderTarget, const gl::ColorF &clearColorValue, diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/src/libANGLE/renderer/d3d/d3d9/Renderer9.h index d762f1d8878..9fa5fbfec4c 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.h +++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.h @@ -405,6 +405,7 @@ class Renderer9 : public RendererD3D DebugAnnotator9 *getAnnotator() { return &mAnnotator; } gl::Version getMaxSupportedESVersion() const override; + gl::Version getMaxConformantESVersion() const override; angle::Result clearRenderTarget(const gl::Context *context, RenderTargetD3D *renderTarget, diff --git a/src/libANGLE/renderer/gl/DisplayGL.cpp b/src/libANGLE/renderer/gl/DisplayGL.cpp index 8ea287640dd..318f11c6ee9 100644 --- a/src/libANGLE/renderer/gl/DisplayGL.cpp +++ b/src/libANGLE/renderer/gl/DisplayGL.cpp @@ -71,6 +71,12 @@ egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, return egl::NoError(); } +gl::Version DisplayGL::getMaxConformantESVersion() const +{ + // Always force a 2.0 context unless the user explicitly requests higher + return std::min(getMaxSupportedESVersion(), gl::Version(2, 0)); +} + void DisplayGL::generateExtensions(egl::DisplayExtensions *outExtensions) const { // Advertise robust resource initialization on all OpenGL backends for testing even though it is diff --git a/src/libANGLE/renderer/gl/DisplayGL.h b/src/libANGLE/renderer/gl/DisplayGL.h index 28347dc0bc3..9def38f04f5 100644 --- a/src/libANGLE/renderer/gl/DisplayGL.h +++ b/src/libANGLE/renderer/gl/DisplayGL.h @@ -43,6 +43,8 @@ class DisplayGL : public DisplayImpl egl::Surface *readSurface, gl::Context *context) override; + gl::Version getMaxConformantESVersion() const override; + protected: void generateExtensions(egl::DisplayExtensions *outExtensions) const override; diff --git a/src/libANGLE/renderer/null/DisplayNULL.cpp b/src/libANGLE/renderer/null/DisplayNULL.cpp index 3c78195ee35..103a92b7322 100644 --- a/src/libANGLE/renderer/null/DisplayNULL.cpp +++ b/src/libANGLE/renderer/null/DisplayNULL.cpp @@ -126,6 +126,11 @@ gl::Version DisplayNULL::getMaxSupportedESVersion() const return gl::Version(3, 2); } +gl::Version DisplayNULL::getMaxConformantESVersion() const +{ + return getMaxSupportedESVersion(); +} + SurfaceImpl *DisplayNULL::createWindowSurface(const egl::SurfaceState &state, EGLNativeWindowType window, const egl::AttributeMap &attribs) diff --git a/src/libANGLE/renderer/null/DisplayNULL.h b/src/libANGLE/renderer/null/DisplayNULL.h index 7166f96d193..99b9107bcfe 100644 --- a/src/libANGLE/renderer/null/DisplayNULL.h +++ b/src/libANGLE/renderer/null/DisplayNULL.h @@ -44,6 +44,7 @@ class DisplayNULL : public DisplayImpl egl::Error waitClient(const gl::Context *context) override; egl::Error waitNative(const gl::Context *context, EGLint engine) override; gl::Version getMaxSupportedESVersion() const override; + gl::Version getMaxConformantESVersion() const override; SurfaceImpl *createWindowSurface(const egl::SurfaceState &state, EGLNativeWindowType window, diff --git a/src/libANGLE/renderer/vulkan/DisplayVk.cpp b/src/libANGLE/renderer/vulkan/DisplayVk.cpp index af5ed603b94..cd929f63d59 100644 --- a/src/libANGLE/renderer/vulkan/DisplayVk.cpp +++ b/src/libANGLE/renderer/vulkan/DisplayVk.cpp @@ -167,6 +167,11 @@ gl::Version DisplayVk::getMaxSupportedESVersion() const return mRenderer->getMaxSupportedESVersion(); } +gl::Version DisplayVk::getMaxConformantESVersion() const +{ + return mRenderer->getMaxConformantESVersion(); +} + void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const { outExtensions->createContextRobustness = true; diff --git a/src/libANGLE/renderer/vulkan/DisplayVk.h b/src/libANGLE/renderer/vulkan/DisplayVk.h index 60c5916beca..b3bb9fde6b2 100644 --- a/src/libANGLE/renderer/vulkan/DisplayVk.h +++ b/src/libANGLE/renderer/vulkan/DisplayVk.h @@ -71,6 +71,7 @@ class DisplayVk : public DisplayImpl, public vk::Context EGLSyncImpl *createSync(const egl::AttributeMap &attribs) override; gl::Version getMaxSupportedESVersion() const override; + gl::Version getMaxConformantESVersion() const override; virtual const char *getWSIExtension() const = 0; virtual const char *getWSILayer() const; diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp index 788ddd82859..2503f57dc1a 100644 --- a/src/libANGLE/renderer/vulkan/RendererVk.cpp +++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp @@ -1112,11 +1112,6 @@ gl::Version RendererVk::getMaxSupportedESVersion() const // Current highest supported version gl::Version maxVersion = gl::Version(3, 1); -#if ANGLE_VULKAN_CONFORMANT_CONFIGS_ONLY - // TODO: Disallow ES 3.0+ until supported. http://crbug.com/angleproject/2950 - maxVersion = gl::Version(2, 0); -#endif - // If the command buffer doesn't support queries, we can't support ES3. if (!vk::CommandBuffer::SupportsQueries(mPhysicalDeviceFeatures)) { @@ -1142,6 +1137,12 @@ gl::Version RendererVk::getMaxSupportedESVersion() const return maxVersion; } +gl::Version RendererVk::getMaxConformantESVersion() const +{ + // Always force a 2.0 context unless the user explicitly requests higher + return std::min(getMaxSupportedESVersion(), gl::Version(2, 0)); +} + void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames) { // Use OpenGL line rasterization rules by default. diff --git a/src/libANGLE/renderer/vulkan/RendererVk.h b/src/libANGLE/renderer/vulkan/RendererVk.h index 382a342983d..f52f4943811 100644 --- a/src/libANGLE/renderer/vulkan/RendererVk.h +++ b/src/libANGLE/renderer/vulkan/RendererVk.h @@ -64,6 +64,7 @@ class RendererVk : angle::NonCopyable std::string getRendererDescription() const; gl::Version getMaxSupportedESVersion() const; + gl::Version getMaxConformantESVersion() const; VkInstance getInstance() const { return mInstance; } VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; } diff --git a/src/libANGLE/validationEGL.cpp b/src/libANGLE/validationEGL.cpp index c4f403b2890..8fb991e89e1 100644 --- a/src/libANGLE/validationEGL.cpp +++ b/src/libANGLE/validationEGL.cpp @@ -1164,6 +1164,21 @@ Error ValidateCreateContext(Display *display, } break; + case EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE: + if (!display->getExtensions().createContextBackwardsCompatible) + { + return EglBadAttribute() + << "Attribute EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE " + "requires EGL_ANGLE_create_context_backwards_compatible."; + } + if (value != EGL_TRUE && value != EGL_FALSE) + { + return EglBadAttribute() + << "EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE must be " + "either EGL_TRUE or EGL_FALSE."; + } + break; + default: return EglBadAttribute() << "Unknown attribute."; } diff --git a/src/tests/angle_end2end_tests.gni b/src/tests/angle_end2end_tests.gni index 584b2491aa3..304703873b5 100644 --- a/src/tests/angle_end2end_tests.gni +++ b/src/tests/angle_end2end_tests.gni @@ -130,6 +130,7 @@ angle_end2end_tests_sources = [ "gl_tests/WebGLCompatibilityTest.cpp", "gl_tests/WebGLFramebufferTest.cpp", "gl_tests/WebGLReadOutsideFramebufferTest.cpp", + "egl_tests/EGLBackwardsCompatibleContextTest.cpp", "egl_tests/EGLBlobCacheTest.cpp", "egl_tests/EGLChooseConfigTest.cpp", "egl_tests/EGLContextCompatibilityTest.cpp", diff --git a/src/tests/egl_tests/EGLBackwardsCompatibleContextTest.cpp b/src/tests/egl_tests/EGLBackwardsCompatibleContextTest.cpp new file mode 100644 index 00000000000..59ee1fbeaee --- /dev/null +++ b/src/tests/egl_tests/EGLBackwardsCompatibleContextTest.cpp @@ -0,0 +1,166 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// EGLBackwardsCompatibleContextTest.cpp.cpp: +// Coverage of the EGL_ANGLE_create_context_backwards_compatible extension + +#include + +#include "test_utils/ANGLETest.h" +#include "test_utils/angle_test_configs.h" +#include "test_utils/angle_test_instantiate.h" + +namespace angle +{ + +namespace +{ +std::pair GetCurrentContextVersion() +{ + const char *versionString = reinterpret_cast(glGetString(GL_VERSION)); + EXPECT_TRUE(strstr(versionString, "OpenGL ES") != nullptr); + return {versionString[10] - '0', versionString[12] - '0'}; +} +} // anonymous namespace + +class EGLBackwardsCompatibleContextTest : public ANGLETest +{ + public: + EGLBackwardsCompatibleContextTest() : mDisplay(0) {} + + void testSetUp() override + { + EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE}; + mDisplay = eglGetPlatformDisplayEXT( + EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(EGL_DEFAULT_DISPLAY), dispattrs); + ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY); + + ASSERT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr)); + + int configsCount = 0; + ASSERT_EGL_TRUE(eglGetConfigs(mDisplay, nullptr, 0, &configsCount)); + ASSERT_TRUE(configsCount != 0); + + std::vector configs(configsCount); + ASSERT_EGL_TRUE(eglGetConfigs(mDisplay, configs.data(), configsCount, &configsCount)); + + for (auto config : configs) + { + EGLint surfaceType; + eglGetConfigAttrib(mDisplay, config, EGL_SURFACE_TYPE, &surfaceType); + if (surfaceType & EGL_PBUFFER_BIT) + { + mConfig = config; + break; + } + } + ASSERT_NE(nullptr, mConfig); + + const EGLint pbufferAttribs[] = { + EGL_WIDTH, 500, EGL_HEIGHT, 500, EGL_NONE, + }; + mPbuffer = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttribs); + EXPECT_TRUE(mPbuffer != EGL_NO_SURFACE); + } + + void testTearDown() override + { + eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + if (mPbuffer != EGL_NO_SURFACE) + { + eglDestroySurface(mDisplay, mPbuffer); + } + + eglTerminate(mDisplay); + } + + EGLDisplay mDisplay = EGL_NO_DISPLAY; + EGLSurface mPbuffer = EGL_NO_SURFACE; + EGLConfig mConfig = 0; +}; + +// Test extension presence. All backends should expose this extension +TEST_P(EGLBackwardsCompatibleContextTest, PbufferDifferentConfig) +{ + EXPECT_TRUE( + IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_context_backwards_compatible")); +} + +// Test that disabling backwards compatibility will always return the expected context version +TEST_P(EGLBackwardsCompatibleContextTest, BackwardsCompatibleDisbled) +{ + ANGLE_SKIP_TEST_IF( + !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_context_backwards_compatible")); + + std::pair testVersions[] = { + {1, 0}, {1, 1}, {2, 0}, {3, 0}, {3, 1}, {3, 2}, + }; + + for (const auto &version : testVersions) + { + EGLint attribs[] = {EGL_CONTEXT_MAJOR_VERSION, + version.first, + EGL_CONTEXT_MINOR_VERSION, + version.second, + EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, + EGL_FALSE, + EGL_NONE, + EGL_NONE}; + + EGLContext context = eglCreateContext(mDisplay, mConfig, nullptr, attribs); + if (context == EGL_NO_CONTEXT) + { + // Context version not supported + continue; + } + + ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, mPbuffer, mPbuffer, context)); + + auto contextVersion = GetCurrentContextVersion(); + EXPECT_EQ(version, contextVersion); + + eglDestroyContext(mDisplay, context); + } +} + +// Test that if ES1.1 is supported and a 1.0 context is requested, an ES 1.1 context is returned +TEST_P(EGLBackwardsCompatibleContextTest, BackwardsCompatibleEnabledES1) +{ + ANGLE_SKIP_TEST_IF( + !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_context_backwards_compatible")); + + EGLint es11ContextAttribs[] = { + EGL_CONTEXT_MAJOR_VERSION, 1, EGL_CONTEXT_MINOR_VERSION, 1, EGL_NONE, EGL_NONE}; + + EGLContext es11Context = eglCreateContext(mDisplay, mConfig, nullptr, es11ContextAttribs); + ANGLE_SKIP_TEST_IF(es11Context == EGL_NO_CONTEXT); + + ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, mPbuffer, mPbuffer, es11Context)); + auto es11ContextVersion = GetCurrentContextVersion(); + ASSERT_EQ(std::make_pair(1, 1), es11ContextVersion); + eglDestroyContext(mDisplay, es11Context); + + EGLint es10ContextAttribs[] = { + EGL_CONTEXT_MAJOR_VERSION, 1, EGL_CONTEXT_MINOR_VERSION, 0, EGL_NONE, EGL_NONE}; + + EGLContext es10Context = eglCreateContext(mDisplay, mConfig, nullptr, es10ContextAttribs); + EXPECT_NE(es10Context, EGL_NO_CONTEXT); + + ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, mPbuffer, mPbuffer, es10Context)); + auto es10ContextVersion = GetCurrentContextVersion(); + ASSERT_EQ(std::make_pair(1, 1), es10ContextVersion); + eglDestroyContext(mDisplay, es10Context); +} + +ANGLE_INSTANTIATE_TEST(EGLBackwardsCompatibleContextTest, + WithNoFixture(ES2_D3D9()), + WithNoFixture(ES2_D3D11()), + WithNoFixture(ES2_OPENGL()), + WithNoFixture(ES2_OPENGLES()), + WithNoFixture(ES2_VULKAN())); + +} // namespace angle diff --git a/src/tests/egl_tests/EGLQueryContextTest.cpp b/src/tests/egl_tests/EGLQueryContextTest.cpp index 5dcb37a7c0b..c8eba3242b5 100644 --- a/src/tests/egl_tests/EGLQueryContextTest.cpp +++ b/src/tests/egl_tests/EGLQueryContextTest.cpp @@ -86,7 +86,7 @@ TEST_P(EGLQueryContextTest, GetClientVersion) EGLint clientVersion; EXPECT_TRUE(eglQueryContext(mDisplay, mContext, EGL_CONTEXT_CLIENT_VERSION, &clientVersion) != EGL_FALSE); - EXPECT_TRUE(clientVersion == GetParam().majorVersion); + EXPECT_GE(clientVersion, GetParam().majorVersion); } TEST_P(EGLQueryContextTest, GetRenderBufferNoSurface) diff --git a/src/tests/test_utils/angle_test_instantiate.cpp b/src/tests/test_utils/angle_test_instantiate.cpp index 9aa673397b0..b398bf64a3d 100644 --- a/src/tests/test_utils/angle_test_instantiate.cpp +++ b/src/tests/test_utils/angle_test_instantiate.cpp @@ -242,14 +242,6 @@ bool IsConfigWhitelisted(const SystemInfo &systemInfo, const PlatformParameters return true; } -#if ANGLE_VULKAN_CONFORMANT_CONFIGS_ONLY - // Vulkan ES 3.0 is not yet supported. - if (param.majorVersion > 2 && param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) - { - return false; - } -#endif - if (IsWindows()) { switch (param.driver) diff --git a/util/EGLWindow.cpp b/util/EGLWindow.cpp index dcd8cb753c1..b7a1d93e542 100644 --- a/util/EGLWindow.cpp +++ b/util/EGLWindow.cpp @@ -345,6 +345,14 @@ EGLContext EGLWindow::createContext(EGLContext share) const return EGL_NO_CONTEXT; } + bool hasBackwardsCompatibleContextExtension = + strstr(displayExtensions, "EGL_ANGLE_create_context_backwards_compatible") != nullptr; + if (!hasProgramCacheControlExtension) + { + std::cerr << "EGL_ANGLE_create_context_backwards_compatible missing.\n"; + return EGL_NO_CONTEXT; + } + eglBindAPI(EGL_OPENGL_ES_API); if (eglGetError() != EGL_SUCCESS) { @@ -413,6 +421,13 @@ EGLContext EGLWindow::createContext(EGLContext share) const mConfigParams.contextProgramCacheEnabled.value() ? EGL_TRUE : EGL_FALSE); } + if (hasBackwardsCompatibleContextExtension) + { + // Always request the exact context version that the config wants + contextAttributes.push_back(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE); + contextAttributes.push_back(EGL_FALSE); + } + bool hasRobustResourceInit = strstr(displayExtensions, "EGL_ANGLE_robust_resource_initialization") != nullptr; if (hasRobustResourceInit && mConfigParams.robustResourceInit.valid())