LCOV - code coverage report
Current view: top level - gfx/gl - GLContextProviderEGL.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 435 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #if defined(MOZ_WIDGET_GTK)
       7             :     #include <gdk/gdkx.h>
       8             :     // we're using default display for now
       9             :     #define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow*)aWidget->GetNativeData(NS_NATIVE_WINDOW)))
      10             :     #define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) ((EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow*)aWidget->RealWidget()->GetNativeData(NS_NATIVE_WINDOW)))
      11             : #elif defined(MOZ_WIDGET_ANDROID)
      12             :     #define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_JAVA_SURFACE))
      13             :     #define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) (aWidget->AsAndroid()->GetEGLNativeWindow())
      14             : #elif defined(XP_WIN)
      15             :     #define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
      16             :     #define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->AsWindows()->GetHwnd())
      17             : #else
      18             :     #define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
      19             :     #define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->RealWidget()->GetNativeData(NS_NATIVE_WINDOW))
      20             : #endif
      21             : 
      22             : #if defined(XP_UNIX)
      23             :     #ifdef MOZ_WIDGET_ANDROID
      24             :         #include <android/native_window.h>
      25             :         #include <android/native_window_jni.h>
      26             :         #include "mozilla/widget/AndroidCompositorWidget.h"
      27             :     #endif
      28             : 
      29             :     #define GLES2_LIB "libGLESv2.so"
      30             :     #define GLES2_LIB2 "libGLESv2.so.2"
      31             : 
      32             : #elif defined(XP_WIN)
      33             :     #include "mozilla/widget/WinCompositorWidget.h"
      34             :     #include "nsIFile.h"
      35             : 
      36             :     #define GLES2_LIB "libGLESv2.dll"
      37             : 
      38             :     #ifndef WIN32_LEAN_AND_MEAN
      39             :         #define WIN32_LEAN_AND_MEAN 1
      40             :     #endif
      41             : 
      42             :     #include <windows.h>
      43             : #else
      44             :     #error "Platform not recognized"
      45             : #endif
      46             : 
      47             : #include "gfxASurface.h"
      48             : #include "gfxCrashReporterUtils.h"
      49             : #include "gfxFailure.h"
      50             : #include "gfxPlatform.h"
      51             : #include "gfxUtils.h"
      52             : #include "GLBlitHelper.h"
      53             : #include "GLContextEGL.h"
      54             : #include "GLContextProvider.h"
      55             : #include "GLLibraryEGL.h"
      56             : #include "mozilla/ArrayUtils.h"
      57             : #include "mozilla/Preferences.h"
      58             : #include "mozilla/gfx/gfxVars.h"
      59             : #include "mozilla/layers/CompositorOptions.h"
      60             : #include "mozilla/widget/CompositorWidget.h"
      61             : #include "nsDebug.h"
      62             : #include "nsIWidget.h"
      63             : #include "nsThreadUtils.h"
      64             : #include "ScopedGLHelpers.h"
      65             : #include "TextureImageEGL.h"
      66             : 
      67             : using namespace mozilla::gfx;
      68             : 
      69             : namespace mozilla {
      70             : namespace gl {
      71             : 
      72             : using namespace mozilla::widget;
      73             : 
      74             : #define ADD_ATTR_2(_array, _k, _v) do {         \
      75             :     (_array).AppendElement(_k);                 \
      76             :     (_array).AppendElement(_v);                 \
      77             : } while (0)
      78             : 
      79             : #define ADD_ATTR_1(_array, _k) do {             \
      80             :     (_array).AppendElement(_k);                 \
      81             : } while (0)
      82             : 
      83             : static bool
      84             : CreateConfig(EGLConfig* aConfig, bool aEnableDepthBuffer);
      85             : 
      86             : // append three zeros at the end of attribs list to work around
      87             : // EGL implementation bugs that iterate until they find 0, instead of
      88             : // EGL_NONE. See bug 948406.
      89             : #define EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS \
      90             :      LOCAL_EGL_NONE, 0, 0, 0
      91             : 
      92             : static EGLint kTerminationAttribs[] = {
      93             :     EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
      94             : };
      95             : 
      96             : static int
      97           0 : next_power_of_two(int v)
      98             : {
      99           0 :     v--;
     100           0 :     v |= v >> 1;
     101           0 :     v |= v >> 2;
     102           0 :     v |= v >> 4;
     103           0 :     v |= v >> 8;
     104           0 :     v |= v >> 16;
     105           0 :     v++;
     106             : 
     107           0 :     return v;
     108             : }
     109             : 
     110             : static bool
     111           0 : is_power_of_two(int v)
     112             : {
     113           0 :     NS_ASSERTION(v >= 0, "bad value");
     114             : 
     115           0 :     if (v == 0)
     116           0 :         return true;
     117             : 
     118           0 :     return (v & (v-1)) == 0;
     119             : }
     120             : 
     121             : static void
     122           0 : DestroySurface(EGLSurface oldSurface) {
     123           0 :     if (oldSurface != EGL_NO_SURFACE) {
     124           0 :         sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
     125             :                                  EGL_NO_SURFACE, EGL_NO_SURFACE,
     126           0 :                                  EGL_NO_CONTEXT);
     127           0 :         sEGLLibrary.fDestroySurface(EGL_DISPLAY(), oldSurface);
     128             :     }
     129           0 : }
     130             : 
     131             : static EGLSurface
     132           0 : CreateSurfaceFromNativeWindow(EGLNativeWindowType window, const EGLConfig& config) {
     133           0 :     EGLSurface newSurface = nullptr;
     134             : 
     135           0 :     MOZ_ASSERT(window);
     136             : #ifdef MOZ_WIDGET_ANDROID
     137             :     JNIEnv* const env = jni::GetEnvForThread();
     138             :     ANativeWindow* const nativeWindow = ANativeWindow_fromSurface(
     139             :             env, reinterpret_cast<jobject>(window));
     140             :     newSurface = sEGLLibrary.fCreateWindowSurface(
     141             :             sEGLLibrary.fGetDisplay(EGL_DEFAULT_DISPLAY),
     142             :             config, nativeWindow, 0);
     143             :     ANativeWindow_release(nativeWindow);
     144             : #else
     145           0 :     newSurface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config,
     146           0 :                                                   window, 0);
     147             : #endif
     148           0 :     return newSurface;
     149             : }
     150             : 
     151             : /* GLContextEGLFactory class was added as a friend of GLContextEGL
     152             :  * so that it could access  GLContextEGL::CreateGLContext. This was
     153             :  * done so that a new function would not need to be added to the shared
     154             :  * GLContextProvider interface.
     155             :  */
     156             : class GLContextEGLFactory {
     157             : public:
     158             :     static already_AddRefed<GLContext> Create(EGLNativeWindowType aWindow,
     159             :                                               bool aWebRender);
     160             : private:
     161             :     GLContextEGLFactory(){}
     162             :     ~GLContextEGLFactory(){}
     163             : };
     164             : 
     165             : already_AddRefed<GLContext>
     166           0 : GLContextEGLFactory::Create(EGLNativeWindowType aWindow,
     167             :                             bool aWebRender)
     168             : {
     169           0 :     MOZ_ASSERT(aWindow);
     170           0 :     nsCString discardFailureId;
     171           0 :     if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) {
     172           0 :         MOZ_CRASH("GFX: Failed to load EGL library 3!\n");
     173             :         return nullptr;
     174             :     }
     175             : 
     176           0 :     bool doubleBuffered = true;
     177             : 
     178             :     EGLConfig config;
     179           0 :     if (!CreateConfig(&config, aWebRender)) {
     180           0 :         MOZ_CRASH("GFX: Failed to create EGLConfig!\n");
     181             :         return nullptr;
     182             :     }
     183             : 
     184           0 :     EGLSurface surface = mozilla::gl::CreateSurfaceFromNativeWindow(aWindow, config);
     185             : 
     186           0 :     if (!surface) {
     187           0 :         MOZ_CRASH("GFX: Failed to create EGLSurface!\n");
     188             :         return nullptr;
     189             :     }
     190             : 
     191           0 :     CreateContextFlags flags = CreateContextFlags::NONE;
     192           0 :     if (aWebRender) {
     193           0 :         flags |= CreateContextFlags::PREFER_ES3;
     194             :     }
     195           0 :     SurfaceCaps caps = SurfaceCaps::Any();
     196           0 :     RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(flags, caps, false, config,
     197           0 :                                                             surface, &discardFailureId);
     198           0 :     if (!gl) {
     199           0 :         MOZ_CRASH("GFX: Failed to create EGLContext!\n");
     200             :         mozilla::gl::DestroySurface(surface);
     201             :         return nullptr;
     202             :     }
     203             : 
     204           0 :     gl->MakeCurrent();
     205           0 :     gl->SetIsDoubleBuffered(doubleBuffered);
     206             : 
     207           0 :     return gl.forget();
     208             : }
     209             : 
     210           0 : GLContextEGL::GLContextEGL(CreateContextFlags flags, const SurfaceCaps& caps,
     211             :                            bool isOffscreen, EGLConfig config, EGLSurface surface,
     212           0 :                            EGLContext context)
     213           0 :     : GLContext(flags, caps, nullptr, isOffscreen, sEGLLibrary.IsANGLE())
     214             :     , mConfig(config)
     215             :     , mSurface(surface)
     216             :     , mContext(context)
     217             :     , mSurfaceOverride(EGL_NO_SURFACE)
     218             :     , mThebesSurface(nullptr)
     219             :     , mBound(false)
     220             :     , mIsPBuffer(false)
     221             :     , mIsDoubleBuffered(false)
     222             :     , mCanBindToTexture(false)
     223             :     , mShareWithEGLImage(false)
     224           0 :     , mOwnsContext(true)
     225             : {
     226             : #ifdef DEBUG
     227           0 :     printf_stderr("Initializing context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
     228             : #endif
     229           0 : }
     230             : 
     231           0 : GLContextEGL::~GLContextEGL()
     232             : {
     233           0 :     MarkDestroyed();
     234             : 
     235             :     // Wrapped context should not destroy eglContext/Surface
     236           0 :     if (!mOwnsContext) {
     237           0 :         return;
     238             :     }
     239             : 
     240             : #ifdef DEBUG
     241           0 :     printf_stderr("Destroying context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
     242             : #endif
     243             : 
     244           0 :     sEGLLibrary.fDestroyContext(EGL_DISPLAY(), mContext);
     245           0 :     sEGLLibrary.UnsetCachedCurrentContext();
     246             : 
     247           0 :     mozilla::gl::DestroySurface(mSurface);
     248           0 : }
     249             : 
     250             : bool
     251           0 : GLContextEGL::Init()
     252             : {
     253             : #if defined(ANDROID)
     254             :     // We can't use LoadApitraceLibrary here because the GLContext
     255             :     // expects its own handle to the GL library
     256             :     if (!OpenLibrary(APITRACE_LIB))
     257             : #endif
     258           0 :         if (!OpenLibrary(GLES2_LIB)) {
     259             : #if defined(XP_UNIX)
     260           0 :             if (!OpenLibrary(GLES2_LIB2)) {
     261           0 :                 NS_WARNING("Couldn't load GLES2 LIB.");
     262           0 :                 return false;
     263             :             }
     264             : #endif
     265             :         }
     266             : 
     267           0 :     SetupLookupFunction();
     268           0 :     if (!InitWithPrefix("gl", true))
     269           0 :         return false;
     270             : 
     271           0 :     bool current = MakeCurrent();
     272           0 :     if (!current) {
     273           0 :         gfx::LogFailure(NS_LITERAL_CSTRING(
     274           0 :             "Couldn't get device attachments for device."));
     275           0 :         return false;
     276             :     }
     277             : 
     278             :     static_assert(sizeof(GLint) >= sizeof(int32_t), "GLint is smaller than int32_t");
     279           0 :     mMaxTextureImageSize = INT32_MAX;
     280             : 
     281           0 :     mShareWithEGLImage = sEGLLibrary.HasKHRImageBase() &&
     282           0 :                           sEGLLibrary.HasKHRImageTexture2D() &&
     283           0 :                           IsExtensionSupported(OES_EGL_image);
     284             : 
     285           0 :     return true;
     286             : }
     287             : 
     288             : bool
     289           0 : GLContextEGL::BindTexImage()
     290             : {
     291           0 :     if (!mSurface)
     292           0 :         return false;
     293             : 
     294           0 :     if (mBound && !ReleaseTexImage())
     295           0 :         return false;
     296             : 
     297           0 :     EGLBoolean success = sEGLLibrary.fBindTexImage(EGL_DISPLAY(),
     298           0 :         (EGLSurface)mSurface, LOCAL_EGL_BACK_BUFFER);
     299           0 :     if (success == LOCAL_EGL_FALSE)
     300           0 :         return false;
     301             : 
     302           0 :     mBound = true;
     303           0 :     return true;
     304             : }
     305             : 
     306             : bool
     307           0 : GLContextEGL::ReleaseTexImage()
     308             : {
     309           0 :     if (!mBound)
     310           0 :         return true;
     311             : 
     312           0 :     if (!mSurface)
     313           0 :         return false;
     314             : 
     315             :     EGLBoolean success;
     316           0 :     success = sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(),
     317             :                                             (EGLSurface)mSurface,
     318           0 :                                             LOCAL_EGL_BACK_BUFFER);
     319           0 :     if (success == LOCAL_EGL_FALSE)
     320           0 :         return false;
     321             : 
     322           0 :     mBound = false;
     323           0 :     return true;
     324             : }
     325             : 
     326             : void
     327           0 : GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf) {
     328           0 :     if (Screen()) {
     329             :         /* Blit `draw` to `read` if we need to, before we potentially juggle
     330             :           * `read` around. If we don't, we might attach a different `read`,
     331             :           * and *then* hit AssureBlitted, which will blit a dirty `draw` onto
     332             :           * the wrong `read`!
     333             :           */
     334           0 :         Screen()->AssureBlitted();
     335             :     }
     336             : 
     337           0 :     mSurfaceOverride = surf;
     338           0 :     DebugOnly<bool> ok = MakeCurrent(true);
     339           0 :     MOZ_ASSERT(ok);
     340           0 : }
     341             : 
     342             : bool
     343           0 : GLContextEGL::MakeCurrentImpl(bool aForce) {
     344           0 :     bool succeeded = true;
     345             : 
     346             :     // Assume that EGL has the same problem as WGL does,
     347             :     // where MakeCurrent with an already-current context is
     348             :     // still expensive.
     349           0 :     bool hasDifferentContext = false;
     350           0 :     if (sEGLLibrary.CachedCurrentContext() != mContext) {
     351             :         // even if the cached context doesn't match the current one
     352             :         // might still
     353           0 :         if (sEGLLibrary.fGetCurrentContext() != mContext) {
     354           0 :             hasDifferentContext = true;
     355             :         } else {
     356           0 :             sEGLLibrary.SetCachedCurrentContext(mContext);
     357             :         }
     358             :     }
     359             : 
     360           0 :     if (aForce || hasDifferentContext) {
     361           0 :         EGLSurface surface = mSurfaceOverride != EGL_NO_SURFACE
     362           0 :                               ? mSurfaceOverride
     363           0 :                               : mSurface;
     364           0 :         if (surface == EGL_NO_SURFACE) {
     365           0 :             return false;
     366             :         }
     367           0 :         succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
     368             :                                               surface, surface,
     369           0 :                                               mContext);
     370           0 :         if (!succeeded) {
     371           0 :             int eglError = sEGLLibrary.fGetError();
     372           0 :             if (eglError == LOCAL_EGL_CONTEXT_LOST) {
     373           0 :                 mContextLost = true;
     374           0 :                 NS_WARNING("EGL context has been lost.");
     375             :             } else {
     376           0 :                 NS_WARNING("Failed to make GL context current!");
     377             : #ifdef DEBUG
     378           0 :                 printf_stderr("EGL Error: 0x%04x\n", eglError);
     379             : #endif
     380             :             }
     381             :         } else {
     382           0 :             sEGLLibrary.SetCachedCurrentContext(mContext);
     383           0 :         }
     384             :     } else {
     385           0 :         MOZ_ASSERT(sEGLLibrary.CachedCurrentContextMatches());
     386             :     }
     387             : 
     388           0 :     return succeeded;
     389             : }
     390             : 
     391             : bool
     392           0 : GLContextEGL::IsCurrent() {
     393           0 :     return sEGLLibrary.fGetCurrentContext() == mContext;
     394             : }
     395             : 
     396             : bool
     397           0 : GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
     398           0 :     if (!mOwnsContext) {
     399           0 :         return false;
     400             :     }
     401             :     // unconditionally release the surface and create a new one. Don't try to optimize this away.
     402             :     // If we get here, then by definition we know that we want to get a new surface.
     403           0 :     ReleaseSurface();
     404           0 :     MOZ_ASSERT(aWidget);
     405           0 :     mSurface = mozilla::gl::CreateSurfaceFromNativeWindow(GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget), mConfig);
     406           0 :     if (!mSurface) {
     407           0 :         return false;
     408             :     }
     409           0 :     return MakeCurrent(true);
     410             : }
     411             : 
     412             : void
     413           0 : GLContextEGL::ReleaseSurface() {
     414           0 :     if (mOwnsContext) {
     415           0 :         mozilla::gl::DestroySurface(mSurface);
     416             :     }
     417           0 :     if (mSurface == mSurfaceOverride) {
     418           0 :         mSurfaceOverride = EGL_NO_SURFACE;
     419             :     }
     420           0 :     mSurface = EGL_NO_SURFACE;
     421           0 : }
     422             : 
     423             : bool
     424           0 : GLContextEGL::SetupLookupFunction()
     425             : {
     426           0 :     mLookupFunc = sEGLLibrary.GetLookupFunction();
     427           0 :     return true;
     428             : }
     429             : 
     430             : bool
     431           0 : GLContextEGL::SwapBuffers()
     432             : {
     433           0 :     EGLSurface surface = mSurfaceOverride != EGL_NO_SURFACE
     434           0 :                           ? mSurfaceOverride
     435           0 :                           : mSurface;
     436           0 :     if (surface) {
     437           0 :         return sEGLLibrary.fSwapBuffers(EGL_DISPLAY(), surface);
     438             :     } else {
     439           0 :         return false;
     440             :     }
     441             : }
     442             : 
     443             : void
     444           0 : GLContextEGL::GetWSIInfo(nsCString* const out) const
     445             : {
     446           0 :     out->AppendLiteral("EGL_VENDOR: ");
     447           0 :     out->Append((const char*)sEGLLibrary.fQueryString(EGL_DISPLAY(), LOCAL_EGL_VENDOR));
     448             : 
     449           0 :     out->AppendLiteral("\nEGL_VERSION: ");
     450           0 :     out->Append((const char*)sEGLLibrary.fQueryString(EGL_DISPLAY(), LOCAL_EGL_VERSION));
     451             : 
     452           0 :     out->AppendLiteral("\nEGL_EXTENSIONS: ");
     453           0 :     out->Append((const char*)sEGLLibrary.fQueryString(EGL_DISPLAY(), LOCAL_EGL_EXTENSIONS));
     454             : 
     455             : #ifndef ANDROID // This query will crash some old android.
     456           0 :     out->AppendLiteral("\nEGL_EXTENSIONS(nullptr): ");
     457           0 :     out->Append((const char*)sEGLLibrary.fQueryString(nullptr, LOCAL_EGL_EXTENSIONS));
     458             : #endif
     459           0 : }
     460             : 
     461             : // hold a reference to the given surface
     462             : // for the lifetime of this context.
     463             : void
     464           0 : GLContextEGL::HoldSurface(gfxASurface* aSurf) {
     465           0 :     mThebesSurface = aSurf;
     466           0 : }
     467             : 
     468             : already_AddRefed<GLContextEGL>
     469           0 : GLContextEGL::CreateGLContext(CreateContextFlags flags,
     470             :                 const SurfaceCaps& caps,
     471             :                 bool isOffscreen,
     472             :                 EGLConfig config,
     473             :                 EGLSurface surface,
     474             :                 nsACString* const out_failureId)
     475             : {
     476           0 :     if (sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API) == LOCAL_EGL_FALSE) {
     477           0 :         *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_ES");
     478           0 :         NS_WARNING("Failed to bind API to GLES!");
     479           0 :         return nullptr;
     480             :     }
     481             : 
     482           0 :     std::vector<EGLint> required_attribs;
     483           0 :     required_attribs.push_back(LOCAL_EGL_CONTEXT_CLIENT_VERSION);
     484           0 :     if (flags & CreateContextFlags::PREFER_ES3) {
     485           0 :         required_attribs.push_back(3);
     486             :     } else {
     487           0 :         required_attribs.push_back(2);
     488             :     }
     489             : 
     490           0 :     std::vector<EGLint> robustness_attribs;
     491           0 :     std::vector<EGLint> rbab_attribs; // RBAB: Robust Buffer Access Behavior
     492           0 :     if (flags & CreateContextFlags::PREFER_ROBUSTNESS) {
     493           0 :         if (sEGLLibrary.IsExtensionSupported(GLLibraryEGL::EXT_create_context_robustness)) {
     494           0 :             robustness_attribs = required_attribs;
     495           0 :             robustness_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
     496           0 :             robustness_attribs.push_back(LOCAL_EGL_LOSE_CONTEXT_ON_RESET_EXT);
     497             :             // Skip EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, since it doesn't help us.
     498             :         }
     499             : 
     500           0 :         if (sEGLLibrary.IsExtensionSupported(GLLibraryEGL::KHR_create_context) &&
     501           0 :             !sEGLLibrary.IsANGLE())
     502             :         {
     503           0 :             rbab_attribs = required_attribs;
     504           0 :             rbab_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR);
     505           0 :             rbab_attribs.push_back(LOCAL_EGL_LOSE_CONTEXT_ON_RESET_KHR);
     506           0 :             rbab_attribs.push_back(LOCAL_EGL_CONTEXT_FLAGS_KHR);
     507           0 :             rbab_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
     508             :         }
     509             :     }
     510             : 
     511           0 :     const auto fnCreate = [&](const std::vector<EGLint>& attribs) {
     512           0 :         auto terminated_attribs = attribs;
     513             : 
     514           0 :         for (const auto& cur : kTerminationAttribs) {
     515           0 :             terminated_attribs.push_back(cur);
     516             :         }
     517             : 
     518           0 :         return sEGLLibrary.fCreateContext(EGL_DISPLAY(), config, EGL_NO_CONTEXT,
     519           0 :                                           terminated_attribs.data());
     520           0 :     };
     521             : 
     522             :     EGLContext context;
     523             :     do {
     524           0 :         if (rbab_attribs.size()) {
     525           0 :             context = fnCreate(rbab_attribs);
     526           0 :             if (context)
     527           0 :                 break;
     528           0 :             NS_WARNING("Failed to create EGLContext with rbab_attribs");
     529             :         }
     530             : 
     531           0 :         if (robustness_attribs.size()) {
     532           0 :             context = fnCreate(robustness_attribs);
     533           0 :             if (context)
     534           0 :                 break;
     535           0 :             NS_WARNING("Failed to create EGLContext with robustness_attribs");
     536             :         }
     537             : 
     538           0 :         context = fnCreate(required_attribs);
     539           0 :         if (context)
     540           0 :             break;
     541           0 :         NS_WARNING("Failed to create EGLContext with required_attribs");
     542             : 
     543           0 :         *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_CREATE");
     544           0 :         return nullptr;
     545             :     } while (false);
     546           0 :     MOZ_ASSERT(context);
     547             : 
     548             :     RefPtr<GLContextEGL> glContext = new GLContextEGL(flags, caps, isOffscreen, config,
     549           0 :                                                       surface, context);
     550           0 :     if (!glContext->Init()) {
     551           0 :         *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_INIT");
     552           0 :         return nullptr;
     553             :     }
     554             : 
     555           0 :     return glContext.forget();
     556             : }
     557             : 
     558             : EGLSurface
     559           0 : GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config,
     560             :                                                    EGLenum bindToTextureFormat,
     561             :                                                    mozilla::gfx::IntSize& pbsize)
     562             : {
     563           0 :     nsTArray<EGLint> pbattrs(16);
     564           0 :     EGLSurface surface = nullptr;
     565             : 
     566             : TRY_AGAIN_POWER_OF_TWO:
     567           0 :     pbattrs.Clear();
     568           0 :     pbattrs.AppendElement(LOCAL_EGL_WIDTH); pbattrs.AppendElement(pbsize.width);
     569           0 :     pbattrs.AppendElement(LOCAL_EGL_HEIGHT); pbattrs.AppendElement(pbsize.height);
     570             : 
     571           0 :     if (bindToTextureFormat != LOCAL_EGL_NONE) {
     572           0 :         pbattrs.AppendElement(LOCAL_EGL_TEXTURE_TARGET);
     573           0 :         pbattrs.AppendElement(LOCAL_EGL_TEXTURE_2D);
     574             : 
     575           0 :         pbattrs.AppendElement(LOCAL_EGL_TEXTURE_FORMAT);
     576           0 :         pbattrs.AppendElement(bindToTextureFormat);
     577             :     }
     578             : 
     579           0 :     for (const auto& cur : kTerminationAttribs) {
     580           0 :         pbattrs.AppendElement(cur);
     581             :     }
     582             : 
     583           0 :     surface = sEGLLibrary.fCreatePbufferSurface(EGL_DISPLAY(), config, &pbattrs[0]);
     584           0 :     if (!surface) {
     585           0 :         if (!is_power_of_two(pbsize.width) ||
     586           0 :             !is_power_of_two(pbsize.height))
     587             :         {
     588           0 :             if (!is_power_of_two(pbsize.width))
     589           0 :                 pbsize.width = next_power_of_two(pbsize.width);
     590           0 :             if (!is_power_of_two(pbsize.height))
     591           0 :                 pbsize.height = next_power_of_two(pbsize.height);
     592             : 
     593           0 :             NS_WARNING("Failed to create pbuffer, trying power of two dims");
     594           0 :             goto TRY_AGAIN_POWER_OF_TWO;
     595             :         }
     596             : 
     597           0 :         NS_WARNING("Failed to create pbuffer surface");
     598           0 :         return nullptr;
     599             :     }
     600             : 
     601           0 :     return surface;
     602             : }
     603             : 
     604             : static const EGLint kEGLConfigAttribsOffscreenPBuffer[] = {
     605             :     LOCAL_EGL_SURFACE_TYPE,    LOCAL_EGL_PBUFFER_BIT,
     606             :     LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
     607             :     // Old versions of llvmpipe seem to need this to properly create the pbuffer (bug 981856)
     608             :     LOCAL_EGL_RED_SIZE,        8,
     609             :     LOCAL_EGL_GREEN_SIZE,      8,
     610             :     LOCAL_EGL_BLUE_SIZE,       8,
     611             :     LOCAL_EGL_ALPHA_SIZE,      0,
     612             :     EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
     613             : };
     614             : 
     615             : static const EGLint kEGLConfigAttribsRGB16[] = {
     616             :     LOCAL_EGL_SURFACE_TYPE,    LOCAL_EGL_WINDOW_BIT,
     617             :     LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
     618             :     LOCAL_EGL_RED_SIZE,        5,
     619             :     LOCAL_EGL_GREEN_SIZE,      6,
     620             :     LOCAL_EGL_BLUE_SIZE,       5,
     621             :     LOCAL_EGL_ALPHA_SIZE,      0,
     622             :     EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
     623             : };
     624             : 
     625             : static const EGLint kEGLConfigAttribsRGB24[] = {
     626             :     LOCAL_EGL_SURFACE_TYPE,    LOCAL_EGL_WINDOW_BIT,
     627             :     LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
     628             :     LOCAL_EGL_RED_SIZE,        8,
     629             :     LOCAL_EGL_GREEN_SIZE,      8,
     630             :     LOCAL_EGL_BLUE_SIZE,       8,
     631             :     LOCAL_EGL_ALPHA_SIZE,      0,
     632             :     EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
     633             : };
     634             : 
     635             : static const EGLint kEGLConfigAttribsRGBA32[] = {
     636             :     LOCAL_EGL_SURFACE_TYPE,    LOCAL_EGL_WINDOW_BIT,
     637             :     LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
     638             :     LOCAL_EGL_RED_SIZE,        8,
     639             :     LOCAL_EGL_GREEN_SIZE,      8,
     640             :     LOCAL_EGL_BLUE_SIZE,       8,
     641             :     LOCAL_EGL_ALPHA_SIZE,      8,
     642             :     EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
     643             : };
     644             : 
     645             : static bool
     646           0 : CreateConfig(EGLConfig* aConfig, int32_t depth, bool aEnableDepthBuffer)
     647             : {
     648             :     EGLConfig configs[64];
     649             :     const EGLint* attribs;
     650           0 :     EGLint ncfg = ArrayLength(configs);
     651             : 
     652           0 :     switch (depth) {
     653             :         case 16:
     654           0 :             attribs = kEGLConfigAttribsRGB16;
     655           0 :             break;
     656             :         case 24:
     657           0 :             attribs = kEGLConfigAttribsRGB24;
     658           0 :             break;
     659             :         case 32:
     660           0 :             attribs = kEGLConfigAttribsRGBA32;
     661           0 :             break;
     662             :         default:
     663           0 :             NS_ERROR("Unknown pixel depth");
     664           0 :             return false;
     665             :     }
     666             : 
     667           0 :     if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(), attribs,
     668           0 :                                    configs, ncfg, &ncfg) ||
     669           0 :         ncfg < 1) {
     670           0 :         return false;
     671             :     }
     672             : 
     673           0 :     for (int j = 0; j < ncfg; ++j) {
     674           0 :         EGLConfig config = configs[j];
     675             :         EGLint r, g, b, a;
     676           0 :         if (sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
     677           0 :                                          LOCAL_EGL_RED_SIZE, &r) &&
     678           0 :             sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
     679           0 :                                          LOCAL_EGL_GREEN_SIZE, &g) &&
     680           0 :             sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
     681           0 :                                          LOCAL_EGL_BLUE_SIZE, &b) &&
     682           0 :             sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
     683           0 :                                          LOCAL_EGL_ALPHA_SIZE, &a) &&
     684           0 :             ((depth == 16 && r == 5 && g == 6 && b == 5) ||
     685           0 :              (depth == 24 && r == 8 && g == 8 && b == 8) ||
     686           0 :              (depth == 32 && r == 8 && g == 8 && b == 8 && a == 8)))
     687             :         {
     688             :             EGLint z;
     689           0 :             if (aEnableDepthBuffer) {
     690           0 :                 if (!sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config, LOCAL_EGL_DEPTH_SIZE, &z) ||
     691           0 :                     z != 24) {
     692           0 :                     continue;
     693             :                 }
     694             :             }
     695           0 :             *aConfig = config;
     696           0 :             return true;
     697             :         }
     698             :     }
     699           0 :     return false;
     700             : }
     701             : 
     702             : // Return true if a suitable EGLConfig was found and pass it out
     703             : // through aConfig.  Return false otherwise.
     704             : //
     705             : // NB: It's entirely legal for the returned EGLConfig to be valid yet
     706             : // have the value null.
     707             : static bool
     708           0 : CreateConfig(EGLConfig* aConfig, bool aEnableDepthBuffer)
     709             : {
     710           0 :     int32_t depth = gfxVars::ScreenDepth();
     711           0 :     if (!CreateConfig(aConfig, depth, aEnableDepthBuffer)) {
     712             : #ifdef MOZ_WIDGET_ANDROID
     713             :         // Bug 736005
     714             :         // Android doesn't always support 16 bit so also try 24 bit
     715             :         if (depth == 16) {
     716             :             return CreateConfig(aConfig, 24, aEnableDepthBuffer);
     717             :         }
     718             :         // Bug 970096
     719             :         // Some devices that have 24 bit screens only support 16 bit OpenGL?
     720             :         if (depth == 24) {
     721             :             return CreateConfig(aConfig, 16, aEnableDepthBuffer);
     722             :         }
     723             : #endif
     724           0 :         return false;
     725             :     } else {
     726           0 :         return true;
     727             :     }
     728             : }
     729             : 
     730             : already_AddRefed<GLContext>
     731           0 : GLContextProviderEGL::CreateWrappingExisting(void* aContext, void* aSurface)
     732             : {
     733           0 :     nsCString discardFailureId;
     734           0 :     if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) {
     735           0 :         MOZ_CRASH("GFX: Failed to load EGL library 2!\n");
     736             :         return nullptr;
     737             :     }
     738             : 
     739           0 :     if (!aContext || !aSurface)
     740           0 :         return nullptr;
     741             : 
     742           0 :     SurfaceCaps caps = SurfaceCaps::Any();
     743           0 :     EGLConfig config = EGL_NO_CONFIG;
     744             :     RefPtr<GLContextEGL> gl = new GLContextEGL(CreateContextFlags::NONE, caps, false,
     745             :                                                config, (EGLSurface)aSurface,
     746           0 :                                                (EGLContext)aContext);
     747           0 :     gl->SetIsDoubleBuffered(true);
     748           0 :     gl->mOwnsContext = false;
     749             : 
     750           0 :     return gl.forget();
     751             : }
     752             : 
     753             : already_AddRefed<GLContext>
     754           0 : GLContextProviderEGL::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated)
     755             : {
     756           0 :     MOZ_ASSERT(aCompositorWidget);
     757           0 :     return GLContextEGLFactory::Create(GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aCompositorWidget),
     758           0 :                                        aCompositorWidget->GetCompositorOptions().UseWebRender());
     759             : }
     760             : 
     761             : already_AddRefed<GLContext>
     762           0 : GLContextProviderEGL::CreateForWindow(nsIWidget* aWidget,
     763             :                                       bool aWebRender,
     764             :                                       bool aForceAccelerated)
     765             : {
     766           0 :     MOZ_ASSERT(aWidget);
     767           0 :     return GLContextEGLFactory::Create(GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget),
     768           0 :                                        aWebRender);
     769             : }
     770             : 
     771             : #if defined(ANDROID)
     772             : EGLSurface
     773             : GLContextProviderEGL::CreateEGLSurface(void* aWindow)
     774             : {
     775             :     // NOTE: aWindow is an ANativeWindow
     776             :     nsCString discardFailureId;
     777             :     if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) {
     778             :         MOZ_CRASH("GFX: Failed to load EGL library 4!\n");
     779             :     }
     780             : 
     781             :     EGLConfig config;
     782             :     if (!CreateConfig(&config, /* aEnableDepthBuffer */ false)) {
     783             :         MOZ_CRASH("GFX: Failed to create EGLConfig 2!\n");
     784             :     }
     785             : 
     786             :     MOZ_ASSERT(aWindow);
     787             : 
     788             :     EGLSurface surface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, aWindow,
     789             :                                                           0);
     790             :     if (surface == EGL_NO_SURFACE) {
     791             :         MOZ_CRASH("GFX: Failed to create EGLSurface 2!\n");
     792             :     }
     793             : 
     794             :     return surface;
     795             : }
     796             : 
     797             : void
     798             : GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface)
     799             : {
     800             :     nsCString discardFailureId;
     801             :     if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) {
     802             :         MOZ_CRASH("GFX: Failed to load EGL library 5!\n");
     803             :     }
     804             : 
     805             :     sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
     806             : }
     807             : #endif // defined(ANDROID)
     808             : 
     809             : static void
     810           0 : FillContextAttribs(bool alpha, bool depth, bool stencil, bool bpp16,
     811             :                    bool es3, nsTArray<EGLint>* out)
     812             : {
     813           0 :     out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
     814           0 :     out->AppendElement(LOCAL_EGL_PBUFFER_BIT);
     815             : 
     816           0 :     out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
     817           0 :     if (es3) {
     818           0 :         out->AppendElement(LOCAL_EGL_OPENGL_ES3_BIT_KHR);
     819             :     } else {
     820           0 :         out->AppendElement(LOCAL_EGL_OPENGL_ES2_BIT);
     821             :     }
     822             : 
     823           0 :     out->AppendElement(LOCAL_EGL_RED_SIZE);
     824           0 :     if (bpp16) {
     825           0 :         out->AppendElement(alpha ? 4 : 5);
     826             :     } else {
     827           0 :         out->AppendElement(8);
     828             :     }
     829             : 
     830           0 :     out->AppendElement(LOCAL_EGL_GREEN_SIZE);
     831           0 :     if (bpp16) {
     832           0 :         out->AppendElement(alpha ? 4 : 6);
     833             :     } else {
     834           0 :         out->AppendElement(8);
     835             :     }
     836             : 
     837           0 :     out->AppendElement(LOCAL_EGL_BLUE_SIZE);
     838           0 :     if (bpp16) {
     839           0 :         out->AppendElement(alpha ? 4 : 5);
     840             :     } else {
     841           0 :         out->AppendElement(8);
     842             :     }
     843             : 
     844           0 :     out->AppendElement(LOCAL_EGL_ALPHA_SIZE);
     845           0 :     if (alpha) {
     846           0 :         out->AppendElement(bpp16 ? 4 : 8);
     847             :     } else {
     848           0 :         out->AppendElement(0);
     849             :     }
     850             : 
     851           0 :     out->AppendElement(LOCAL_EGL_DEPTH_SIZE);
     852           0 :     out->AppendElement(depth ? 16 : 0);
     853             : 
     854           0 :     out->AppendElement(LOCAL_EGL_STENCIL_SIZE);
     855           0 :     out->AppendElement(stencil ? 8 : 0);
     856             : 
     857             :     // EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
     858           0 :     out->AppendElement(LOCAL_EGL_NONE);
     859           0 :     out->AppendElement(0);
     860             : 
     861           0 :     out->AppendElement(0);
     862           0 :     out->AppendElement(0);
     863           0 : }
     864             : 
     865             : static GLint
     866           0 : GetAttrib(GLLibraryEGL* egl, EGLConfig config, EGLint attrib)
     867             : {
     868           0 :     EGLint bits = 0;
     869           0 :     egl->fGetConfigAttrib(egl->Display(), config, attrib, &bits);
     870           0 :     MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
     871             : 
     872           0 :     return bits;
     873             : }
     874             : 
     875             : static EGLConfig
     876           0 : ChooseConfig(GLLibraryEGL* egl, CreateContextFlags flags, const SurfaceCaps& minCaps,
     877             :              SurfaceCaps* const out_configCaps)
     878             : {
     879           0 :     nsTArray<EGLint> configAttribList;
     880           0 :     FillContextAttribs(minCaps.alpha, minCaps.depth, minCaps.stencil, minCaps.bpp16,
     881           0 :                        bool(flags & CreateContextFlags::PREFER_ES3), &configAttribList);
     882             : 
     883           0 :     const EGLint* configAttribs = configAttribList.Elements();
     884             : 
     885             :     // We're guaranteed to get at least minCaps, and the sorting dictated by the spec for
     886             :     // eglChooseConfig reasonably assures that a reasonable 'best' config is on top.
     887           0 :     const EGLint kMaxConfigs = 1;
     888             :     EGLConfig configs[kMaxConfigs];
     889           0 :     EGLint foundConfigs = 0;
     890           0 :     if (!egl->fChooseConfig(egl->Display(), configAttribs, configs, kMaxConfigs,
     891             :                             &foundConfigs)
     892           0 :         || foundConfigs == 0)
     893             :     {
     894           0 :         return EGL_NO_CONFIG;
     895             :     }
     896             : 
     897           0 :     EGLConfig config = configs[0];
     898             : 
     899           0 :     *out_configCaps = minCaps; // Pick up any preserve, etc.
     900           0 :     out_configCaps->color = true;
     901           0 :     out_configCaps->alpha   = bool(GetAttrib(egl, config, LOCAL_EGL_ALPHA_SIZE));
     902           0 :     out_configCaps->depth   = bool(GetAttrib(egl, config, LOCAL_EGL_DEPTH_SIZE));
     903           0 :     out_configCaps->stencil = bool(GetAttrib(egl, config, LOCAL_EGL_STENCIL_SIZE));
     904           0 :     out_configCaps->bpp16 = (GetAttrib(egl, config, LOCAL_EGL_RED_SIZE) < 8);
     905             : 
     906           0 :     return config;
     907             : }
     908             : 
     909             : /*static*/ already_AddRefed<GLContextEGL>
     910           0 : GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
     911             :                                                const mozilla::gfx::IntSize& size,
     912             :                                                const SurfaceCaps& minCaps,
     913             :                                                nsACString* const out_failureId)
     914             : {
     915           0 :     bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
     916           0 :     if (!sEGLLibrary.EnsureInitialized(forceEnableHardware, out_failureId)) {
     917           0 :         return nullptr;
     918             :     }
     919             : 
     920           0 :     SurfaceCaps configCaps;
     921           0 :     EGLConfig config = ChooseConfig(&sEGLLibrary, flags, minCaps, &configCaps);
     922           0 :     if (config == EGL_NO_CONFIG) {
     923           0 :         *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_NO_CONFIG");
     924           0 :         NS_WARNING("Failed to find a compatible config.");
     925           0 :         return nullptr;
     926             :     }
     927             : 
     928           0 :     if (GLContext::ShouldSpew()) {
     929           0 :         sEGLLibrary.DumpEGLConfig(config);
     930             :     }
     931             : 
     932           0 :     mozilla::gfx::IntSize pbSize(size);
     933             :     EGLSurface surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
     934             :                                                                             LOCAL_EGL_NONE,
     935           0 :                                                                             pbSize);
     936           0 :     if (!surface) {
     937           0 :         *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_POT");
     938           0 :         NS_WARNING("Failed to create PBuffer for context!");
     939           0 :         return nullptr;
     940             :     }
     941             : 
     942           0 :     RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(flags, configCaps, true,
     943             :                                                             config, surface,
     944           0 :                                                             out_failureId);
     945           0 :     if (!gl) {
     946           0 :         NS_WARNING("Failed to create GLContext from PBuffer");
     947           0 :         sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
     948           0 :         return nullptr;
     949             :     }
     950             : 
     951           0 :     return gl.forget();
     952             : }
     953             : 
     954             : /*static*/ already_AddRefed<GLContext>
     955           0 : GLContextProviderEGL::CreateHeadless(CreateContextFlags flags,
     956             :                                      nsACString* const out_failureId)
     957             : {
     958           0 :     mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16);
     959           0 :     SurfaceCaps dummyCaps = SurfaceCaps::Any();
     960           0 :     return GLContextEGL::CreateEGLPBufferOffscreenContext(flags, dummySize, dummyCaps,
     961           0 :                                                           out_failureId);
     962             : }
     963             : 
     964             : // Under EGL, on Android, pbuffers are supported fine, though
     965             : // often without the ability to texture from them directly.
     966             : /*static*/ already_AddRefed<GLContext>
     967           0 : GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size,
     968             :                                       const SurfaceCaps& minCaps,
     969             :                                       CreateContextFlags flags,
     970             :                                       nsACString* const out_failureId)
     971             : {
     972           0 :     bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
     973           0 :     if (!sEGLLibrary.EnsureInitialized(forceEnableHardware, out_failureId)) { // Needed for IsANGLE().
     974           0 :         return nullptr;
     975             :     }
     976             : 
     977           0 :     bool canOffscreenUseHeadless = true;
     978           0 :     if (sEGLLibrary.IsANGLE()) {
     979             :         // ANGLE needs to use PBuffers.
     980           0 :         canOffscreenUseHeadless = false;
     981             :     }
     982             : 
     983           0 :     RefPtr<GLContext> gl;
     984           0 :     SurfaceCaps minOffscreenCaps = minCaps;
     985             : 
     986           0 :     if (canOffscreenUseHeadless) {
     987           0 :         gl = CreateHeadless(flags, out_failureId);
     988           0 :         if (!gl) {
     989           0 :             return nullptr;
     990             :         }
     991             :     } else {
     992           0 :         SurfaceCaps minBackbufferCaps = minOffscreenCaps;
     993           0 :         if (minOffscreenCaps.antialias) {
     994           0 :             minBackbufferCaps.antialias = false;
     995           0 :             minBackbufferCaps.depth = false;
     996           0 :             minBackbufferCaps.stencil = false;
     997             :         }
     998             : 
     999           0 :         gl = GLContextEGL::CreateEGLPBufferOffscreenContext(flags, size,
    1000             :                                                             minBackbufferCaps,
    1001           0 :                                                             out_failureId);
    1002           0 :         if (!gl)
    1003           0 :             return nullptr;
    1004             : 
    1005             :         // Pull the actual resulting caps to ensure that our offscreen matches our
    1006             :         // backbuffer.
    1007           0 :         minOffscreenCaps.alpha = gl->Caps().alpha;
    1008           0 :         if (!minOffscreenCaps.antialias) {
    1009             :             // Only update these if we don't have AA. If we do have AA, we ignore
    1010             :             // backbuffer depth/stencil.
    1011           0 :             minOffscreenCaps.depth = gl->Caps().depth;
    1012           0 :             minOffscreenCaps.stencil = gl->Caps().stencil;
    1013             :         }
    1014             :     }
    1015             : 
    1016             :     // Init the offscreen with the updated offscreen caps.
    1017           0 :     if (!gl->InitOffscreen(size, minOffscreenCaps)) {
    1018           0 :         *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_OFFSCREEN");
    1019           0 :         return nullptr;
    1020             :     }
    1021             : 
    1022           0 :     return gl.forget();
    1023             : }
    1024             : 
    1025             : // Don't want a global context on Android as 1) share groups across 2 threads fail on many Tegra drivers (bug 759225)
    1026             : // and 2) some mobile devices have a very strict limit on global number of GL contexts (bug 754257)
    1027             : // and 3) each EGL context eats 750k on B2G (bug 813783)
    1028             : /*static*/ GLContext*
    1029           0 : GLContextProviderEGL::GetGlobalContext()
    1030             : {
    1031           0 :     return nullptr;
    1032             : }
    1033             : 
    1034             : /*static*/ void
    1035           0 : GLContextProviderEGL::Shutdown()
    1036             : {
    1037           0 : }
    1038             : 
    1039             : } /* namespace gl */
    1040             : } /* namespace mozilla */
    1041             : 
    1042             : #undef EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS

Generated by: LCOV version 1.13