Commit 89ef177f by Geoff Lang Committed by Commit Bot

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/1131555Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent 6cad7736
...@@ -109,9 +109,6 @@ void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const ...@@ -109,9 +109,6 @@ void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
// Contexts are virtualized so textures can be shared globally // Contexts are virtualized so textures can be shared globally
outExtensions->displayTextureShareGroup = true; 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 // We will fallback to regular swap if swapBuffersWithDamage isn't
// supported, so indicate support here to keep validation happy. // supported, so indicate support here to keep validation happy.
outExtensions->swapBuffersWithDamage = true; outExtensions->swapBuffersWithDamage = true;
......
...@@ -30,11 +30,12 @@ class DisplayEGL : public DisplayGL ...@@ -30,11 +30,12 @@ class DisplayEGL : public DisplayGL
const egl::AttributeMap &eglAttributes, const egl::AttributeMap &eglAttributes,
EGLContext *outContext) const; EGLContext *outContext) const;
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
FunctionsEGL *mEGL; FunctionsEGL *mEGL;
EGLConfig mConfig; EGLConfig mConfig;
private: private:
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
void generateCaps(egl::Caps *outCaps) const override; void generateCaps(egl::Caps *outCaps) const override;
}; };
......
...@@ -42,6 +42,7 @@ static constexpr bool kDefaultEGLVirtualizedContexts = true; ...@@ -42,6 +42,7 @@ static constexpr bool kDefaultEGLVirtualizedContexts = true;
DisplayAndroid::DisplayAndroid(const egl::DisplayState &state) DisplayAndroid::DisplayAndroid(const egl::DisplayState &state)
: DisplayEGL(state), : DisplayEGL(state),
mVirtualizedContexts(kDefaultEGLVirtualizedContexts), mVirtualizedContexts(kDefaultEGLVirtualizedContexts),
mSupportsSurfaceless(false),
mDummyPbuffer(EGL_NO_SURFACE) mDummyPbuffer(EGL_NO_SURFACE)
{ {
} }
...@@ -126,7 +127,8 @@ egl::Error DisplayAndroid::initialize(egl::Display *display) ...@@ -126,7 +127,8 @@ egl::Error DisplayAndroid::initialize(egl::Display *display)
} }
// A dummy pbuffer is only needed if surfaceless contexts are not supported. // 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[] = { int dummyPbufferAttribs[] = {
EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE,
...@@ -499,6 +501,22 @@ egl::Error DisplayAndroid::makeCurrent(egl::Surface *drawSurface, ...@@ -499,6 +501,22 @@ egl::Error DisplayAndroid::makeCurrent(egl::Surface *drawSurface,
newContext == currentContext.context); newContext == currentContext.context);
newContext = mRenderer->getContext(); 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) if (newSurface != currentContext.surface || newContext != currentContext.context)
...@@ -535,6 +553,15 @@ void DisplayAndroid::destroyNativeContext(EGLContext context) ...@@ -535,6 +553,15 @@ void DisplayAndroid::destroyNativeContext(EGLContext context)
} }
} }
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) egl::Error DisplayAndroid::makeCurrentSurfaceless(gl::Context *context)
{ {
// Nothing to do because EGL always uses the same context and the previous surface can be left // Nothing to do because EGL always uses the same context and the previous surface can be left
......
...@@ -73,6 +73,8 @@ class DisplayAndroid : public DisplayEGL ...@@ -73,6 +73,8 @@ class DisplayAndroid : public DisplayEGL
void destroyNativeContext(EGLContext context) override; void destroyNativeContext(EGLContext context) override;
private: private:
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
egl::Error createRenderer(EGLContext shareContext, egl::Error createRenderer(EGLContext shareContext,
bool makeNewContextCurrent, bool makeNewContextCurrent,
std::shared_ptr<RendererEGL> *outRenderer); std::shared_ptr<RendererEGL> *outRenderer);
...@@ -94,6 +96,8 @@ class DisplayAndroid : public DisplayEGL ...@@ -94,6 +96,8 @@ class DisplayAndroid : public DisplayEGL
egl::AttributeMap mDisplayAttributes; egl::AttributeMap mDisplayAttributes;
bool mSupportsSurfaceless;
std::vector<EGLint> mConfigAttribList; std::vector<EGLint> mConfigAttribList;
std::map<EGLint, EGLint> mConfigIds; std::map<EGLint, EGLint> mConfigIds;
EGLSurface mDummyPbuffer; EGLSurface mDummyPbuffer;
......
...@@ -1009,6 +1009,14 @@ void DisplayOzone::setSwapInterval(EGLSurface drawable, SwapControlData *data) ...@@ -1009,6 +1009,14 @@ void DisplayOzone::setSwapInterval(EGLSurface drawable, SwapControlData *data)
ASSERT(data != nullptr); 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) egl::Error DisplayOzone::makeCurrentSurfaceless(gl::Context *context)
{ {
// Nothing to do, handled in the GL layers // Nothing to do, handled in the GL layers
......
...@@ -156,6 +156,8 @@ class DisplayOzone final : public DisplayEGL ...@@ -156,6 +156,8 @@ class DisplayOzone final : public DisplayEGL
void setSwapInterval(EGLSurface drawable, SwapControlData *data); void setSwapInterval(EGLSurface drawable, SwapControlData *data);
private: private:
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
egl::Error makeCurrentSurfaceless(gl::Context *context) override; egl::Error makeCurrentSurfaceless(gl::Context *context) override;
GLuint makeShader(GLuint type, const char *src); GLuint makeShader(GLuint type, const char *src);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment