opengl: Add support for EGL 1.4 without EGL_KHR_surfaceless_context.
This is core in EGL 1.5 but not in EGL 1.4. Without it we need to create
a pbuffer to set as an offscreen surface when there is no window to
render to.
Bug: 42241384
Change-Id: I046bcdd878d49ec18d7b9e43a600feb653b046c5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/195918
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/opengl/ContextEGL.cpp b/src/dawn/native/opengl/ContextEGL.cpp
index f1b7c4e..d9b6835 100644
--- a/src/dawn/native/opengl/ContextEGL.cpp
+++ b/src/dawn/native/opengl/ContextEGL.cpp
@@ -54,6 +54,10 @@
ContextEGL::ContextEGL(const DisplayEGL* display) : mDisplay(display) {}
ContextEGL::~ContextEGL() {
+ if (mOffscreenSurface != EGL_NO_SURFACE) {
+ mDisplay->egl.DestroySurface(mDisplay->GetDisplay(), mOffscreenSurface);
+ mOffscreenSurface = EGL_NO_SURFACE;
+ }
if (mContext != EGL_NO_CONTEXT) {
mDisplay->egl.DestroyContext(mDisplay->GetDisplay(), mContext);
mContext = EGL_NO_CONTEXT;
@@ -68,14 +72,15 @@
// Unless EGL_KHR_no_config is present, we need to choose an EGLConfig on context creation that
// will lock the EGLContext to be use with a single kind of color buffer. In that case the
// display should only list one kind of color buffer as potentially supported.
- EGLConfig config = kNoConfig;
+ EGLConfig contextConfig = kNoConfig;
if (!egl.HasExt(EGLExt::NoConfigContext)) {
DAWN_ASSERT(mDisplay->GetPotentialSurfaceFormats().size() == 1);
wgpu::TextureFormat format = mDisplay->GetPotentialSurfaceFormats()[0];
- config = mDisplay->ChooseConfig(EGL_WINDOW_BIT, format);
- if (config == kNoConfig) {
- return DAWN_FORMAT_INTERNAL_ERROR("Couldn't find an EGLConfig for %s.", format);
+ contextConfig = mDisplay->ChooseConfig(EGL_WINDOW_BIT, format);
+ if (contextConfig == kNoConfig) {
+ return DAWN_FORMAT_INTERNAL_ERROR(
+ "Couldn't find an EGLConfig rendering to a window for %s.", format);
}
}
@@ -121,13 +126,41 @@
attribs.push_back(EGL_NONE);
- mContext = egl.CreateContext(mDisplay->GetDisplay(), config, EGL_NO_CONTEXT, attribs.data());
- return CheckEGL(egl, mContext != EGL_NO_CONTEXT, "eglCreateContext");
+ mContext =
+ egl.CreateContext(mDisplay->GetDisplay(), contextConfig, EGL_NO_CONTEXT, attribs.data());
+ DAWN_TRY(CheckEGL(egl, mContext != EGL_NO_CONTEXT, "eglCreateContext"));
+
+ // When EGL_KHR_surfaceless_context is not supported, we need to create a pbuffer to act
+ // as an offscreen surface.
+ if (!egl.HasExt(EGLExt::SurfacelessContext)) {
+ // The first potential surface format is always a good choice to find the config. Either we
+ // only support this one and the context will be compatible with the pbuffer, or
+ // EGL_KHR_no_config_context is supported and the context is compatible with any config.
+ wgpu::TextureFormat format = mDisplay->GetPotentialSurfaceFormats()[0];
+
+ EGLConfig pbufferConfig = mDisplay->ChooseConfig(EGL_PBUFFER_BIT, format);
+ if (pbufferConfig == kNoConfig) {
+ return DAWN_FORMAT_INTERNAL_ERROR(
+ "Couldn't find an EGLConfig rendering to a window for %s.", format);
+ }
+
+ EGLint pbufferAttribs[] = {
+ EGL_WIDTH, 1, //
+ EGL_HEIGHT, 1, //
+ EGL_NONE,
+ };
+ mOffscreenSurface =
+ egl.CreatePbufferSurface(mDisplay->GetDisplay(), pbufferConfig, pbufferAttribs);
+ DAWN_TRY(
+ CheckEGL(egl, mOffscreenSurface != EGL_NO_SURFACE, "Creating the offscreen surface."));
+ }
+
+ return {};
}
void ContextEGL::MakeCurrent() {
- EGLBoolean success =
- mDisplay->egl.MakeCurrent(mDisplay->GetDisplay(), mSurface, mSurface, mContext);
+ EGLBoolean success = mDisplay->egl.MakeCurrent(mDisplay->GetDisplay(), mCurrentSurface,
+ mCurrentSurface, mContext);
IgnoreErrors(CheckEGL(mDisplay->egl, success == EGL_TRUE, "eglMakeCurrent"));
}
@@ -141,11 +174,11 @@
ContextEGL::ScopedMakeSurfaceCurrent::ScopedMakeSurfaceCurrent(ContextEGL* context,
EGLSurface surface)
: mContext(context) {
- mContext->mSurface = surface;
+ mContext->mCurrentSurface = surface;
}
ContextEGL::ScopedMakeSurfaceCurrent::~ScopedMakeSurfaceCurrent() {
- mContext->mSurface = EGL_NO_SURFACE;
+ mContext->mCurrentSurface = mContext->mOffscreenSurface;
}
} // namespace dawn::native::opengl
diff --git a/src/dawn/native/opengl/ContextEGL.h b/src/dawn/native/opengl/ContextEGL.h
index 281f4a2..8595440 100644
--- a/src/dawn/native/opengl/ContextEGL.h
+++ b/src/dawn/native/opengl/ContextEGL.h
@@ -71,7 +71,8 @@
private:
raw_ptr<const DisplayEGL> mDisplay;
EGLContext mContext = EGL_NO_CONTEXT;
- EGLSurface mSurface = EGL_NO_SURFACE;
+ EGLSurface mCurrentSurface = EGL_NO_SURFACE;
+ EGLSurface mOffscreenSurface = EGL_NO_SURFACE;
};
} // namespace dawn::native::opengl