Bug 1370544 - Ensure EGLSurface is created with the same EGLConfig as the context r=jgilbert
authorRandall Barker <rbarker@mozilla.com>
Tue, 06 Jun 2017 17:26:49 -0700
changeset 372574 599b64980e2d44cd81b1f6837d8e416f4e951823
parent 372573 3b7a0f88829436f1b82630ebb7cc0f1c8cf04172
child 372575 2e6dbfb4f07a4fae364882ecc8e368151698cd21
push id32279
push userarchaeopteryx@coole-files.de
push dateThu, 03 Aug 2017 09:46:19 +0000
treeherdermozilla-central@63e261ce8cb0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1370544
milestone56.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 1370544 - Ensure EGLSurface is created with the same EGLConfig as the context r=jgilbert MozReview-Commit-ID: 1cN7VzCa2lV
gfx/gl/GLContextEGL.h
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLContextProviderImpl.h
gfx/gl/SharedSurfaceEGL.cpp
gfx/layers/composite/LayerManagerComposite.cpp
--- a/gfx/gl/GLContextEGL.h
+++ b/gfx/gl/GLContextEGL.h
@@ -128,14 +128,18 @@ protected:
     bool mIsDoubleBuffered;
     bool mCanBindToTexture;
     bool mShareWithEGLImage;
     bool mOwnsContext;
 
     static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config,
                                                            EGLenum bindToTextureFormat,
                                                            gfx::IntSize& pbsize);
+#if defined(MOZ_WIDGET_ANDROID)
+public:
+    EGLSurface CreateCompatibleSurface(void* aWindow);
+#endif // defined(MOZ_WIDGET_ANDROID)
 };
 
 } // namespace gl
 } // namespace mozilla
 
 #endif // GLCONTEXTEGL_H_
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -763,43 +763,52 @@ GLContextProviderEGL::CreateForWindow(ns
                                       bool aWebRender,
                                       bool aForceAccelerated)
 {
     MOZ_ASSERT(aWidget);
     return GLContextEGLFactory::Create(GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget),
                                        aWebRender);
 }
 
-#if defined(ANDROID)
+#if defined(MOZ_WIDGET_ANDROID)
 EGLSurface
-GLContextProviderEGL::CreateEGLSurface(void* aWindow)
+GLContextEGL::CreateCompatibleSurface(void* aWindow)
+{
+    if (mConfig == EGL_NO_CONFIG) {
+        MOZ_CRASH("GFX: Failed with invalid EGLConfig 2!\n");
+    }
+
+    return GLContextProviderEGL::CreateEGLSurface(aWindow, mConfig);
+}
+
+/* static */ EGLSurface
+GLContextProviderEGL::CreateEGLSurface(void* aWindow, EGLConfig aConfig)
 {
     // NOTE: aWindow is an ANativeWindow
     nsCString discardFailureId;
     if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) {
         MOZ_CRASH("GFX: Failed to load EGL library 4!\n");
     }
-
-    EGLConfig config;
-    if (!CreateConfig(&config, /* aEnableDepthBuffer */ false)) {
+    EGLConfig config = aConfig;
+    if (!config && !CreateConfig(&config, /* aEnableDepthBuffer */ false)) {
         MOZ_CRASH("GFX: Failed to create EGLConfig 2!\n");
     }
 
     MOZ_ASSERT(aWindow);
 
     EGLSurface surface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, aWindow,
                                                           0);
     if (surface == EGL_NO_SURFACE) {
         MOZ_CRASH("GFX: Failed to create EGLSurface 2!\n");
     }
 
     return surface;
 }
 
-void
+/* static */ void
 GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface)
 {
     nsCString discardFailureId;
     if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) {
         MOZ_CRASH("GFX: Failed to load EGL library 5!\n");
     }
 
     sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
@@ -975,16 +984,22 @@ GLContextProviderEGL::CreateOffscreen(co
     }
 
     bool canOffscreenUseHeadless = true;
     if (sEGLLibrary.IsANGLE()) {
         // ANGLE needs to use PBuffers.
         canOffscreenUseHeadless = false;
     }
 
+#if defined(MOZ_WIDGET_ANDROID)
+    // Using a headless context loses the SurfaceCaps
+    // which can cause a loss of depth and/or stencil
+    canOffscreenUseHeadless = false;
+#endif //  defined(MOZ_WIDGET_ANDROID)
+
     RefPtr<GLContext> gl;
     SurfaceCaps minOffscreenCaps = minCaps;
 
     if (canOffscreenUseHeadless) {
         gl = CreateHeadless(flags, out_failureId);
         if (!gl) {
             return nullptr;
         }
--- a/gfx/gl/GLContextProviderImpl.h
+++ b/gfx/gl/GLContextProviderImpl.h
@@ -5,19 +5,19 @@
 
 #ifndef IN_GL_CONTEXT_PROVIDER_H
 #error GLContextProviderImpl.h must only be included from GLContextProvider.h
 #endif
 
 #ifndef GL_CONTEXT_PROVIDER_NAME
 #error GL_CONTEXT_PROVIDER_NAME not defined
 #endif
-#if defined(ANDROID)
-typedef void* EGLSurface;
-#endif // defined(ANDROID)
+#if defined(MOZ_WIDGET_ANDROID)
+#include "GLTypes.h" // for EGLSurface and EGLConfig
+#endif // defined(MOZ_WIDGET_ANDROID)
 
 class GL_CONTEXT_PROVIDER_NAME
 {
 public:
     /**
      * Create a context that renders to the surface of the widget represented by
      * the compositor widget that is passed in. The context is always created
      * with an RGB pixel format, with no alpha, depth or stencil.
@@ -107,20 +107,20 @@ public:
      * @param aContext External context which will be wrapped by Gecko GLContext.
      * @param aSurface External surface which is used for external context.
      *
      * @return Wrapping Context to use for rendering
      */
     static already_AddRefed<GLContext>
     CreateWrappingExisting(void* aContext, void* aSurface);
 
-#if defined(ANDROID)
-    static EGLSurface CreateEGLSurface(void* aWindow);
+#if defined(MOZ_WIDGET_ANDROID)
+    static EGLSurface CreateEGLSurface(void* aWindow, EGLConfig aConfig = nullptr);
     static void DestroyEGLSurface(EGLSurface surface);
-#endif // defined(ANDROID)
+#endif // defined(MOZ_WIDGET_ANDROID)
 
     /**
      * Get a pointer to the global context, creating it if it doesn't exist.
      */
     static GLContext*
     GetGlobalContext();
 
     /**
--- a/gfx/gl/SharedSurfaceEGL.cpp
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -191,17 +191,19 @@ SharedSurface_SurfaceTexture::Create(GLC
                                      bool hasAlpha,
                                      java::GeckoSurface::Param surface)
 {
     MOZ_ASSERT(surface);
 
     UniquePtr<SharedSurface_SurfaceTexture> ret;
 
     AndroidNativeWindow window(surface);
-    EGLSurface eglSurface = GLContextProviderEGL::CreateEGLSurface(window.NativeWindow());
+    GLContextEGL* egl = GLContextEGL::Cast(prodGL);
+    MOZ_ASSERT(egl);
+    EGLSurface eglSurface = egl->CreateCompatibleSurface(window.NativeWindow());
     if (!eglSurface) {
         return Move(ret);
     }
 
     ret.reset(new SharedSurface_SurfaceTexture(prodGL, size, hasAlpha,
                                                formats, surface, eglSurface));
     return Move(ret);
 }
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -1066,36 +1066,36 @@ LayerManagerComposite::RenderToPresentat
 {
   widget::CompositorWidget* const widget = mCompositor->GetWidget();
   ANativeWindow* window = widget->AsAndroid()->GetPresentationANativeWindow();
 
   if (!window) {
     return;
   }
 
-  EGLSurface surface = widget->AsAndroid()->GetPresentationEGLSurface();
-
-  if (!surface) {
-    //create surface;
-    surface = GLContextProviderEGL::CreateEGLSurface(window);
-    if (!surface) {
-      return;
-    }
-
-    widget->AsAndroid()->SetPresentationEGLSurface(surface);
-  }
-
   CompositorOGL* compositor = mCompositor->AsCompositorOGL();
   GLContext* gl = compositor->gl();
   GLContextEGL* egl = GLContextEGL::Cast(gl);
 
   if (!egl) {
     return;
   }
 
+  EGLSurface surface = widget->AsAndroid()->GetPresentationEGLSurface();
+
+  if (!surface) {
+    //create surface;
+    surface = egl->CreateCompatibleSurface(window);
+    if (!surface) {
+      return;
+    }
+
+    widget->AsAndroid()->SetPresentationEGLSurface(surface);
+  }
+
   const IntSize windowSize(ANativeWindow_getWidth(window),
                            ANativeWindow_getHeight(window));
 
 
   if ((windowSize.width <= 0) || (windowSize.height <= 0)) {
     return;
   }