EGL: Fix binding EGL_NO_SURFACE without surfaceless support.
It was possible for ANGLE to call eglMakeCurrent with EGL_NO_SURFACE and
a valid context when the client called eglMakeCurrent with
EGL_NO_SURFACE and EGL_NO_CONTEXT. Fix this by always binding a surface
when the driver has no native surfaceless support.
Don't expose the surfaceless extension when it's not possible to support
it (unvirtualized contexts and no native surfaceless support).
BUG=860800
BUG=angleproject:2464
Change-Id: Id8af9638d4356dbd710c453c9f196b9f25a2bbf9
Reviewed-on: https://chromium-review.googlesource.com/1131555
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp b/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
index 1fc32fe..e33728d 100644
--- a/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
+++ b/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
@@ -109,9 +109,6 @@
// Contexts are virtualized so textures can be shared globally
outExtensions->displayTextureShareGroup = true;
- // Surfaceless contexts are emulated even if there is no native support.
- outExtensions->surfacelessContext = true;
-
// We will fallback to regular swap if swapBuffersWithDamage isn't
// supported, so indicate support here to keep validation happy.
outExtensions->swapBuffersWithDamage = true;
diff --git a/src/libANGLE/renderer/gl/egl/DisplayEGL.h b/src/libANGLE/renderer/gl/egl/DisplayEGL.h
index 7533fc5..af64961 100644
--- a/src/libANGLE/renderer/gl/egl/DisplayEGL.h
+++ b/src/libANGLE/renderer/gl/egl/DisplayEGL.h
@@ -30,11 +30,12 @@
const egl::AttributeMap &eglAttributes,
EGLContext *outContext) const;
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+
FunctionsEGL *mEGL;
EGLConfig mConfig;
private:
- void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
void generateCaps(egl::Caps *outCaps) const override;
};
diff --git a/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp b/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
index 64ce9f3..b188ba8 100644
--- a/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
+++ b/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
@@ -42,6 +42,7 @@
DisplayAndroid::DisplayAndroid(const egl::DisplayState &state)
: DisplayEGL(state),
mVirtualizedContexts(kDefaultEGLVirtualizedContexts),
+ mSupportsSurfaceless(false),
mDummyPbuffer(EGL_NO_SURFACE)
{
}
@@ -126,7 +127,8 @@
}
// A dummy pbuffer is only needed if surfaceless contexts are not supported.
- if (!mEGL->hasExtension("EGL_KHR_surfaceless_context"))
+ mSupportsSurfaceless = mEGL->hasExtension("EGL_KHR_surfaceless_context");
+ if (!mSupportsSurfaceless)
{
int dummyPbufferAttribs[] = {
EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE,
@@ -499,6 +501,22 @@
newContext == currentContext.context);
newContext = mRenderer->getContext();
+
+ // If we know that we're only running on one thread (mVirtualizedContexts == true) and
+ // EGL_NO_SURFACE is going to be bound, we can optimize this case by not changing the
+ // surface binding and emulate the surfaceless extension in the frontend.
+ if (newSurface == EGL_NO_SURFACE)
+ {
+ newSurface = currentContext.surface;
+ }
+
+ // It's possible that no surface has been created yet and the driver doesn't support
+ // surfaceless, bind the dummy pbuffer.
+ if (newSurface == EGL_NO_SURFACE && !mSupportsSurfaceless)
+ {
+ newSurface = mDummyPbuffer;
+ ASSERT(newSurface != EGL_NO_SURFACE);
+ }
}
if (newSurface != currentContext.surface || newContext != currentContext.context)
@@ -535,6 +553,15 @@
}
}
+void DisplayAndroid::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ // Surfaceless can be support if the native driver supports it or we know that we are running on
+ // a single thread (mVirtualizedContexts == true)
+ outExtensions->surfacelessContext = mSupportsSurfaceless || mVirtualizedContexts;
+
+ DisplayEGL::generateExtensions(outExtensions);
+}
+
egl::Error DisplayAndroid::makeCurrentSurfaceless(gl::Context *context)
{
// Nothing to do because EGL always uses the same context and the previous surface can be left
diff --git a/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h b/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
index 604cad4..fc99a34 100644
--- a/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
+++ b/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
@@ -73,6 +73,8 @@
void destroyNativeContext(EGLContext context) override;
private:
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+
egl::Error createRenderer(EGLContext shareContext,
bool makeNewContextCurrent,
std::shared_ptr<RendererEGL> *outRenderer);
@@ -94,6 +96,8 @@
egl::AttributeMap mDisplayAttributes;
+ bool mSupportsSurfaceless;
+
std::vector<EGLint> mConfigAttribList;
std::map<EGLint, EGLint> mConfigIds;
EGLSurface mDummyPbuffer;
diff --git a/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp b/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp
index 0c59700..51f5426 100644
--- a/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp
+++ b/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.cpp
@@ -1009,6 +1009,14 @@
ASSERT(data != nullptr);
}
+void DisplayOzone::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ // Surfaceless contexts are emulated even if there is no native support.
+ outExtensions->surfacelessContext = true;
+
+ DisplayEGL::generateExtensions(outExtensions);
+}
+
egl::Error DisplayOzone::makeCurrentSurfaceless(gl::Context *context)
{
// Nothing to do, handled in the GL layers
diff --git a/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h b/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h
index 0200503..b71c990 100644
--- a/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h
+++ b/src/libANGLE/renderer/gl/egl/ozone/DisplayOzone.h
@@ -156,6 +156,8 @@
void setSwapInterval(EGLSurface drawable, SwapControlData *data);
private:
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+
egl::Error makeCurrentSurfaceless(gl::Context *context) override;
GLuint makeShader(GLuint type, const char *src);