Bug 1646135 - Set draw buffer after eglMakeCurrent when using desktop GL,r=gfx-reviewers,lsalzman
authorRobert Mader <robert.mader@posteo.de>
Fri, 25 Jun 2021 15:29:29 +0000
changeset 584435 c2191ee9cb6519c9736108ee1c82599a533ef552
parent 584434 b434222eaaf2c6c880fe92adbbba7bf2a50e57ab
child 584436 6ba608aff7b71ed48fccfc31efa3d64c497e82f3
push id38565
push usermlaza@mozilla.com
push dateFri, 25 Jun 2021 21:51:52 +0000
treeherdermozilla-central@b9a82200b994 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgfx-reviewers, lsalzman
bugs1646135
milestone91.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1646135 - Set draw buffer after eglMakeCurrent when using desktop GL,r=gfx-reviewers,lsalzman Original patch by Erik Kurzinger: D118304 The following is currently not well-defined by the EGL specification: 1. Create context. 2. Make it current with no default framebuffer (as a surface-less context, ie bind EGL_NO_SURFACE for both surfaces) 3. Make it current with a default framebuffer (ie with some draw/read surfaces) After Step #3 what is the current draw buffer state? is it GL_NONE or GL_BACK? With Mesa's EGL implementation, the answer is GL_BACK, and WebRender's EGL backend currently assumes this behavior. However with the proprietary NVIDIA driver the answer is actually GL_NONE, meaning any rendering done after step #3 will be lost. As a fix, Firefox can simple call glDrawBuffer after making a surface current to set the draw buffer appropriately, either to GL_BACK for a double-buffered surface or to GL_FRONT for single-buffered. As mentioned above, this is redundant on Mesa, but should also be harmless. Differential Revision: https://phabricator.services.mozilla.com/D118743
gfx/webrender_bindings/RenderCompositorEGL.cpp
--- a/gfx/webrender_bindings/RenderCompositorEGL.cpp
+++ b/gfx/webrender_bindings/RenderCompositorEGL.cpp
@@ -197,18 +197,28 @@ bool RenderCompositorEGL::Resume() {
 
 bool RenderCompositorEGL::IsPaused() { return mEGLSurface == EGL_NO_SURFACE; }
 
 gl::GLContext* RenderCompositorEGL::gl() const {
   return RenderThread::Get()->SingletonGL();
 }
 
 bool RenderCompositorEGL::MakeCurrent() {
-  gl::GLContextEGL::Cast(gl())->SetEGLSurfaceOverride(mEGLSurface);
-  return gl()->MakeCurrent();
+  const auto& gle = gl::GLContextEGL::Cast(gl());
+
+  gle->SetEGLSurfaceOverride(mEGLSurface);
+  bool ok = gl()->MakeCurrent();
+  if (!gl()->IsGLES() && ok && mEGLSurface != EGL_NO_SURFACE) {
+    // If we successfully made a surface current, set the draw buffer
+    // appropriately. It's not well-defined by the EGL spec whether
+    // eglMakeCurrent should do this automatically. See bug 1646135.
+    gl()->fDrawBuffer(gl()->IsDoubleBuffered() ? LOCAL_GL_BACK
+                                               : LOCAL_GL_FRONT);
+  }
+  return ok;
 }
 
 void RenderCompositorEGL::DestroyEGLSurface() {
   const auto& gle = gl::GLContextEGL::Cast(gl());
   const auto& egl = gle->mEgl;
 
   // Release EGLSurface of back buffer before calling ResizeBuffers().
   if (mEGLSurface) {