Revert "Bug 1972411 - give gnome-shell and pipewire more time to start, and retry the task if we time out. r=jmaher" for causing linux perma failures
This reverts commit 2b905fe7199c9210434f7c7f8326b57025c91c55.
Revert "Bug 1972411 - make /builds/worker/fetches a volume in the test docker image. r=releng-reviewers,Eijebong"
This reverts commit 9d15aecaf6a08b98d3c47f2d0e644e35341b2520.
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */#if defined(MOZ_WIDGET_GTK)# define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) \ ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_EGL_WINDOW))# define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) \ (aWidget->AsGTK()->GetEGLNativeWindow())#elif defined(MOZ_WIDGET_ANDROID)# define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) \ ((EGLNativeWindowType)aWidget->GetNativeData(NS_JAVA_SURFACE))# define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) \ (aWidget->AsAndroid()->GetEGLNativeWindow())#elif defined(XP_WIN)# define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) \ ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))# define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) \ ((EGLNativeWindowType)aWidget->AsWindows()->GetHwnd())#else# define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) \ ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))# define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) \ ((EGLNativeWindowType)aWidget->RealWidget()->GetNativeData( \ NS_NATIVE_WINDOW))#endif#if defined(XP_UNIX)# ifdef MOZ_WIDGET_ANDROID# include <android/native_window.h># include <android/native_window_jni.h># include "mozilla/jni/Utils.h"# include "mozilla/widget/AndroidCompositorWidget.h"# endif# define GLES2_LIB "libGLESv2.so"# define GLES2_LIB2 "libGLESv2.so.2"#elif defined(XP_WIN)# include "mozilla/widget/WinCompositorWidget.h"# include "nsIFile.h"# define GLES2_LIB "libGLESv2.dll"# ifndef WIN32_LEAN_AND_MEAN# define WIN32_LEAN_AND_MEAN 1# endif# include <windows.h>#else# error "Platform not recognized"#endif#include"gfxCrashReporterUtils.h"#include"gfxFailure.h"#include"gfxPlatform.h"#include"gfxUtils.h"#include"GLBlitHelper.h"#include"GLContextEGL.h"#include"GLContextProvider.h"#include"GLLibraryEGL.h"#include"GLLibraryLoader.h"#include"mozilla/ArrayUtils.h"#include"mozilla/Preferences.h"#include"mozilla/Services.h"#include"mozilla/StaticPrefs_gfx.h"#include"mozilla/gfx/gfxVars.h"#include"mozilla/gfx/BuildConstants.h"#include"mozilla/gfx/Logging.h"#include"mozilla/layers/CompositorOptions.h"#include"mozilla/widget/CompositorWidget.h"#include"nsDebug.h"#include"nsIWidget.h"#include"nsThreadUtils.h"#include"ScopedGLHelpers.h"#if defined(MOZ_WIDGET_GTK)# include "mozilla/widget/GtkCompositorWidget.h"# if defined(MOZ_WAYLAND)# include <gdk/gdkwayland.h># include <wayland-egl.h># include "mozilla/WidgetUtilsGtk.h"# include "mozilla/widget/nsWaylandDisplay.h"# endif#endifstructwl_egl_window;usingnamespacemozilla::gfx;namespacemozilla{namespacegl{usingnamespacemozilla::widget;#if defined(MOZ_WAYLAND)classWaylandOffscreenGLSurface{public:WaylandOffscreenGLSurface(structwl_surface*aWaylandSurface,structwl_egl_window*aEGLWindow);~WaylandOffscreenGLSurface();private:structwl_surface*mWaylandSurface=nullptr;structwl_egl_window*mEGLWindow=nullptr;};MOZ_RUNINITstaticnsTHashMap<nsPtrHashKey<void>,WaylandOffscreenGLSurface*>sWaylandOffscreenGLSurfaces;voidDeleteWaylandOffscreenGLSurface(EGLSurfacesurface){autoentry=sWaylandOffscreenGLSurfaces.Lookup(surface);if(entry){deleteentry.Data();entry.Remove();}}#endifstaticboolCreateConfigScreen(EglDisplay&,EGLConfig*constaConfig,constboolaEnableDepthBuffer,constboolaUseGles);// append three zeros at the end of attribs list to work around// EGL implementation bugs that iterate until they find 0, instead of// EGL_NONE. See bug 948406.#define EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS \ LOCAL_EGL_NONE, 0, 0, 0staticEGLintkTerminationAttribs[]={EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS};staticintnext_power_of_two(intv){v--;v|=v>>1;v|=v>>2;v|=v>>4;v|=v>>8;v|=v>>16;v++;returnv;}staticboolis_power_of_two(intv){NS_ASSERTION(v>=0,"bad value");if(v==0)returntrue;return(v&(v-1))==0;}staticEGLSurfaceCreateFallbackSurface(EglDisplay&egl,constEGLConfig&config){if(egl.IsExtensionSupported(EGLExtension::KHR_surfaceless_context)){// We don't need a PBuffer surface in this casereturnEGL_NO_SURFACE;}std::vector<EGLint>pbattrs;pbattrs.push_back(LOCAL_EGL_WIDTH);pbattrs.push_back(1);pbattrs.push_back(LOCAL_EGL_HEIGHT);pbattrs.push_back(1);for(constauto&cur:kTerminationAttribs){pbattrs.push_back(cur);}EGLSurfacesurface=egl.fCreatePbufferSurface(config,pbattrs.data());if(!surface){MOZ_CRASH("Failed to create fallback EGLSurface");}returnsurface;}staticEGLSurfaceCreateSurfaceFromNativeWindow(EglDisplay&egl,constEGLNativeWindowTypewindow,constEGLConfigconfig){MOZ_ASSERT(window);EGLSurfacenewSurface=EGL_NO_SURFACE;#ifdef MOZ_WIDGET_ANDROIDJNIEnv*constenv=jni::GetEnvForThread();ANativeWindow*constnativeWindow=ANativeWindow_fromSurface(env,reinterpret_cast<jobject>(window));if(!nativeWindow){gfxCriticalNote<<"Failed to obtain native window from Surface";returnEGL_NO_SURFACE;}constauto&display=egl.mLib->fGetDisplay(EGL_DEFAULT_DISPLAY);newSurface=egl.mLib->fCreateWindowSurface(display,config,nativeWindow,0);ANativeWindow_release(nativeWindow);#elsenewSurface=egl.fCreateWindowSurface(config,window,0);#endifif(!newSurface){constautoerr=egl.mLib->fGetError();gfxCriticalNote<<"Failed to create EGLSurface!: "<<gfx::hexa(err);}returnnewSurface;}/* GLContextEGLFactory class was added as a friend of GLContextEGL * so that it could access GLContextEGL::CreateGLContext. This was * done so that a new function would not need to be added to the shared * GLContextProvider interface. */classGLContextEGLFactory{public:staticalready_AddRefed<GLContext>Create(EGLNativeWindowTypeaWindow,boolaHardwareWebRender);staticalready_AddRefed<GLContext>CreateImpl(EGLNativeWindowTypeaWindow,boolaHardwareWebRender,boolaUseGles);private:GLContextEGLFactory()=default;~GLContextEGLFactory()=default;};already_AddRefed<GLContext>GLContextEGLFactory::CreateImpl(EGLNativeWindowTypeaWindow,boolaHardwareWebRender,boolaUseGles){nsCStringfailureId;constautolib=GLLibraryEGL::Get(&failureId);if(!lib){gfxCriticalNote<<"Failed[3] to load EGL library: "<<failureId.get();returnnullptr;}constautoegl=lib->CreateDisplay(true,false,&failureId);if(!egl){gfxCriticalNote<<"Failed[3] to create EGL library display: "<<failureId.get();returnnullptr;}booldoubleBuffered=true;EGLConfigconfig;if(aHardwareWebRender&&egl->mLib->IsANGLE()){// Force enable alpha channel to make sure ANGLE use correct framebuffer// formartconstintbpp=32;if(!CreateConfig(*egl,&config,bpp,false,aUseGles)){gfxCriticalNote<<"Failed to create EGLConfig for WebRender ANGLE!";returnnullptr;}}elseif(kIsLinux){constintbpp=32;if(!CreateConfig(*egl,&config,bpp,false,aUseGles)){gfxCriticalNote<<"Failed to create EGLConfig for WebRender!";returnnullptr;}}else{if(!CreateConfigScreen(*egl,&config,/* aEnableDepthBuffer */false,aUseGles)){gfxCriticalNote<<"Failed to create EGLConfig!";returnnullptr;}}EGLSurfacesurface=EGL_NO_SURFACE;if(aWindow){surface=mozilla::gl::CreateSurfaceFromNativeWindow(*egl,aWindow,config);if(!surface){returnnullptr;}}CreateContextFlagsflags=CreateContextFlags::NONE;if(aHardwareWebRender&&StaticPrefs::gfx_webrender_prefer_robustness_AtStartup()){flags|=CreateContextFlags::PREFER_ROBUSTNESS;}if(aHardwareWebRender&&aUseGles){flags|=CreateContextFlags::PREFER_ES3;}if(!aHardwareWebRender){flags|=CreateContextFlags::REQUIRE_COMPAT_PROFILE;}constautodesc=GLContextDesc{{flags},false};RefPtr<GLContextEGL>gl=GLContextEGL::CreateGLContext(egl,desc,config,surface,aUseGles,config,&failureId);if(!gl){constautoerr=egl->mLib->fGetError();gfxCriticalNote<<"Failed to create EGLContext!: "<<gfx::hexa(err);GLContextEGL::DestroySurface(*egl,surface);returnnullptr;}gl->MakeCurrent();gl->SetIsDoubleBuffered(doubleBuffered);#ifdef MOZ_WIDGET_GTKif(surface){constintinterval=gfxVars::SwapIntervalEGL()?1:0;egl->fSwapInterval(interval);}#endifif(aHardwareWebRender&&egl->mLib->IsANGLE()){MOZ_ASSERT(doubleBuffered);constintinterval=gfxVars::SwapIntervalEGL()?1:0;egl->fSwapInterval(interval);}returngl.forget();}already_AddRefed<GLContext>GLContextEGLFactory::Create(EGLNativeWindowTypeaWindow,boolaHardwareWebRender){boolpreferGles;#if defined(MOZ_WIDGET_ANDROID)preferGles=true;#elsepreferGles=StaticPrefs::gfx_egl_prefer_gles_enabled_AtStartup();#endif // defined(MOZ_WIDGET_ANDROID)RefPtr<GLContext>glContext=CreateImpl(aWindow,aHardwareWebRender,preferGles);#if !defined(MOZ_WIDGET_ANDROID)if(!glContext){glContext=CreateImpl(aWindow,aHardwareWebRender,!preferGles);}#endif // !defined(MOZ_WIDGET_ANDROID)returnglContext.forget();}/* static */EGLSurfaceGLContextEGL::CreateEGLSurfaceForCompositorWidget(widget::CompositorWidget*aCompositorWidget,constEGLConfigaConfig){nsCStringdiscardFailureId;constautoegl=DefaultEglDisplay(&discardFailureId);if(!egl){gfxCriticalNote<<"Failed to load EGL library 6!";returnEGL_NO_SURFACE;}MOZ_ASSERT(aCompositorWidget);EGLNativeWindowTypewindow=GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aCompositorWidget);if(!window){#ifdef MOZ_WIDGET_GTK// RenderCompositorEGL does not like EGL_NO_SURFACE as it fallbacks// to SW rendering or claims itself as paused.// In case we're missing valid native window because aCompositorWidget// hidden, just create a fallback EGLSurface. Actual EGLSurface will be// created by widget code later when aCompositorWidget becomes visible.mozilla::gfx::IntSizepbSize(16,16);# ifdef MOZ_WAYLANDif(GdkIsWaylandDisplay()){returnCreateWaylandOffscreenSurface(*egl,aConfig,pbSize);}else# endif{returnCreatePBufferSurfaceTryingPowerOfTwo(*egl,aConfig,LOCAL_EGL_NONE,pbSize);}#elsegfxCriticalNote<<"window is null";returnEGL_NO_SURFACE;#endif}returnmozilla::gl::CreateSurfaceFromNativeWindow(*egl,window,aConfig);}GLContextEGL::GLContextEGL(conststd::shared_ptr<EglDisplay>egl,constGLContextDesc&desc,EGLConfigsurfaceConfig,EGLSurfacesurface,EGLContextcontext):GLContext(desc,nullptr,false),mEgl(egl),mSurfaceConfig(surfaceConfig),mContext(context),mSurface(surface),mFallbackSurface(CreateFallbackSurface(*mEgl,mSurfaceConfig)){#ifdef DEBUGprintf_stderr("Initializing context %p surface %p on display %p\n",mContext,mSurface,mEgl->mDisplay);#endif}voidGLContextEGL::OnMarkDestroyed(){if(mSurfaceOverride!=EGL_NO_SURFACE){SetEGLSurfaceOverride(EGL_NO_SURFACE);}}GLContextEGL::~GLContextEGL(){MarkDestroyed();// Wrapped context should not destroy eglContext/Surfaceif(!mOwnsContext){return;}#ifdef DEBUGprintf_stderr("Destroying context %p surface %p on display %p\n",mContext,mSurface,mEgl->mDisplay);#endifmEgl->fDestroyContext(mContext);DestroySurface(*mEgl,mSurface);DestroySurface(*mEgl,mFallbackSurface);}boolGLContextEGL::Init(){if(!GLContext::Init())returnfalse;boolcurrent=MakeCurrent();if(!current){gfx::LogFailure("Couldn't get device attachments for device."_ns);returnfalse;}mShareWithEGLImage=mEgl->HasKHRImageBase()&&mEgl->IsExtensionSupported(EGLExtension::KHR_gl_texture_2D_image)&&IsExtensionSupported(OES_EGL_image);#if MOZ_WIDGET_ANDROID// We see crashes in eglTerminate on devices with Xclipse GPUs running// Android 14. Choose to leak the EGLDisplays in order to avoid the crashes.// See bug 1868825 and bug 1903810.if(Renderer()==GLRenderer::SamsungXclipse&&jni::GetAPIVersion()>=34){mEgl->SetShouldLeakEGLDisplay();}#endifreturntrue;}boolGLContextEGL::BindTexImage(){if(!mSurface)returnfalse;if(mBound&&!ReleaseTexImage())returnfalse;EGLBooleansuccess=mEgl->fBindTexImage((EGLSurface)mSurface,LOCAL_EGL_BACK_BUFFER);if(success==LOCAL_EGL_FALSE)returnfalse;mBound=true;returntrue;}boolGLContextEGL::ReleaseTexImage(){if(!mBound)returntrue;if(!mSurface)returnfalse;EGLBooleansuccess;success=mEgl->fReleaseTexImage((EGLSurface)mSurface,LOCAL_EGL_BACK_BUFFER);if(success==LOCAL_EGL_FALSE)returnfalse;mBound=false;returntrue;}voidGLContextEGL::SetEGLSurfaceOverride(EGLSurfacesurf){mSurfaceOverride=surf;DebugOnly<bool>ok=MakeCurrent(true);MOZ_ASSERT(ok);}boolGLContextEGL::MakeCurrentImpl()const{EGLSurfacesurface=(mSurfaceOverride!=EGL_NO_SURFACE)?mSurfaceOverride:mSurface;if(!surface){surface=mFallbackSurface;}constboolsucceeded=mEgl->fMakeCurrent(surface,surface,mContext);if(!succeeded){constautoeglError=mEgl->mLib->fGetError();if(eglError==LOCAL_EGL_CONTEXT_LOST){OnContextLostError();}else{NS_WARNING("Failed to make GL context current!");#ifdef DEBUGprintf_stderr("EGL Error: 0x%04x\n",eglError);#endif}}returnsucceeded;}boolGLContextEGL::IsCurrentImpl()const{returnmEgl->mLib->fGetCurrentContext()==mContext;}boolGLContextEGL::RenewSurface(CompositorWidget*aWidget){if(!mOwnsContext){returnfalse;}// unconditionally release the surface and create a new one. Don't try to// optimize this away. If we get here, then by definition we know that we want// to get a new surface.ReleaseSurface();MOZ_ASSERT(aWidget);EGLNativeWindowTypenativeWindow=GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget);if(nativeWindow){mSurface=mozilla::gl::CreateSurfaceFromNativeWindow(*mEgl,nativeWindow,mSurfaceConfig);if(!mSurface){NS_WARNING("Failed to create EGLSurface from native window");returnfalse;}}constboolok=MakeCurrent(true);MOZ_ASSERT(ok);#ifdef MOZ_WIDGET_GTKif(mSurface){constintinterval=gfxVars::SwapIntervalEGL()?1:0;mEgl->fSwapInterval(interval);}#endifreturnok;}voidGLContextEGL::ReleaseSurface(){if(mOwnsContext){DestroySurface(*mEgl,mSurface);}if(mSurface==mSurfaceOverride){mSurfaceOverride=EGL_NO_SURFACE;}mSurface=EGL_NO_SURFACE;}Maybe<SymbolLoader>GLContextEGL::GetSymbolLoader()const{returnmEgl->mLib->GetSymbolLoader();}boolGLContextEGL::SwapBuffers(){EGLSurfacesurface=mSurfaceOverride!=EGL_NO_SURFACE?mSurfaceOverride:mSurface;if(surface){if((mEgl->IsExtensionSupported(EGLExtension::EXT_swap_buffers_with_damage)||mEgl->IsExtensionSupported(EGLExtension::KHR_swap_buffers_with_damage))){std::vector<EGLint>rects;for(autoiter=mDamageRegion.RectIter();!iter.Done();iter.Next()){constIntRect&r=iter.Get();rects.push_back(r.X());rects.push_back(r.Y());rects.push_back(r.Width());rects.push_back(r.Height());}mDamageRegion.SetEmpty();returnmEgl->fSwapBuffersWithDamage(surface,rects.data(),rects.size()/4);}returnmEgl->fSwapBuffers(surface);}else{returnfalse;}}voidGLContextEGL::SetDamage(constnsIntRegion&aDamageRegion){mDamageRegion=aDamageRegion;}voidGLContextEGL::GetWSIInfo(nsCString*constout)const{out->AppendLiteral("EGL_VENDOR: ");out->Append((constchar*)mEgl->mLib->fQueryString(mEgl->mDisplay,LOCAL_EGL_VENDOR));out->AppendLiteral("\nEGL_VERSION: ");out->Append((constchar*)mEgl->mLib->fQueryString(mEgl->mDisplay,LOCAL_EGL_VERSION));out->AppendLiteral("\nEGL_EXTENSIONS: ");out->Append((constchar*)mEgl->mLib->fQueryString(mEgl->mDisplay,LOCAL_EGL_EXTENSIONS));#ifndef ANDROID // This query will crash some old android.out->AppendLiteral("\nEGL_EXTENSIONS(nullptr): ");out->Append((constchar*)mEgl->mLib->fQueryString(nullptr,LOCAL_EGL_EXTENSIONS));#endif}boolGLContextEGL::HasExtBufferAge()const{returnmEgl->IsExtensionSupported(EGLExtension::EXT_buffer_age);}boolGLContextEGL::HasKhrPartialUpdate()const{returnmEgl->IsExtensionSupported(EGLExtension::KHR_partial_update);}GLintGLContextEGL::GetBufferAge()const{EGLSurfacesurface=mSurfaceOverride!=EGL_NO_SURFACE?mSurfaceOverride:mSurface;if(surface&&(HasExtBufferAge()||HasKhrPartialUpdate())){EGLintresult;mEgl->fQuerySurface(surface,LOCAL_EGL_BUFFER_AGE_EXT,&result);returnresult;}return0;}#define LOCAL_EGL_CONTEXT_PROVOKING_VERTEX_DONT_CARE_MOZ 0x6000RefPtr<GLContextEGL>GLContextEGL::CreateGLContext(conststd::shared_ptr<EglDisplay>egl,constGLContextDesc&desc,EGLConfigsurfaceConfig,EGLSurfacesurface,constbooluseGles,EGLConfigcontextConfig,nsACString*constout_failureId){constauto&flags=desc.flags;std::vector<EGLint>required_attribs;if(useGles){// TODO: This fBindAPI could be more thread-safeif(egl->mLib->fBindAPI(LOCAL_EGL_OPENGL_ES_API)==LOCAL_EGL_FALSE){*out_failureId="FEATURE_FAILURE_EGL_ES"_ns;NS_WARNING("Failed to bind API to GLES!");returnnullptr;}required_attribs.push_back(LOCAL_EGL_CONTEXT_MAJOR_VERSION);if(flags&CreateContextFlags::PREFER_ES3){required_attribs.push_back(3);}else{required_attribs.push_back(2);}}else{if(egl->mLib->fBindAPI(LOCAL_EGL_OPENGL_API)==LOCAL_EGL_FALSE){*out_failureId="FEATURE_FAILURE_EGL"_ns;NS_WARNING("Failed to bind API to GL!");returnnullptr;}if(flags&CreateContextFlags::REQUIRE_COMPAT_PROFILE){required_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_PROFILE_MASK);required_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);required_attribs.push_back(LOCAL_EGL_CONTEXT_MAJOR_VERSION);required_attribs.push_back(2);}else{// !REQUIRE_COMPAT_PROFILE means core profle.required_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_PROFILE_MASK);required_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);required_attribs.push_back(LOCAL_EGL_CONTEXT_MAJOR_VERSION);required_attribs.push_back(3);required_attribs.push_back(LOCAL_EGL_CONTEXT_MINOR_VERSION);required_attribs.push_back(2);}}if((flags&CreateContextFlags::PREFER_EXACT_VERSION)&&egl->mLib->IsANGLE()){required_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE);required_attribs.push_back(LOCAL_EGL_FALSE);}constautodebugFlags=GLContext::ChooseDebugFlags(flags);if(!debugFlags&&flags&CreateContextFlags::NO_VALIDATION&&egl->IsExtensionSupported(EGLExtension::KHR_create_context_no_error)){required_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_NO_ERROR_KHR);required_attribs.push_back(LOCAL_EGL_TRUE);}if(flags&CreateContextFlags::PROVOKING_VERTEX_DONT_CARE&&egl->IsExtensionSupported(EGLExtension::MOZ_create_context_provoking_vertex_dont_care)){required_attribs.push_back(LOCAL_EGL_CONTEXT_PROVOKING_VERTEX_DONT_CARE_MOZ);required_attribs.push_back(LOCAL_EGL_TRUE);}std::vector<EGLint>ext_robustness_attribs;std::vector<EGLint>ext_rbab_attribs;// RBAB: Robust Buffer Access Behaviorstd::vector<EGLint>khr_robustness_attribs;std::vector<EGLint>khr_rbab_attribs;// RBAB: Robust Buffer Access Behaviorif(flags&CreateContextFlags::PREFER_ROBUSTNESS){std::vector<EGLint>base_robustness_attribs=required_attribs;if(egl->IsExtensionSupported(EGLExtension::NV_robustness_video_memory_purge)){base_robustness_attribs.push_back(LOCAL_EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV);base_robustness_attribs.push_back(LOCAL_EGL_TRUE);}if(egl->IsExtensionSupported(EGLExtension::EXT_create_context_robustness)){ext_robustness_attribs=base_robustness_attribs;ext_robustness_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);ext_robustness_attribs.push_back(LOCAL_EGL_LOSE_CONTEXT_ON_RESET_EXT);if(gfxVars::AllowEglRbab()){ext_rbab_attribs=ext_robustness_attribs;ext_rbab_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);ext_rbab_attribs.push_back(LOCAL_EGL_TRUE);}}if(egl->IsExtensionSupported(EGLExtension::KHR_create_context)){khr_robustness_attribs=base_robustness_attribs;khr_robustness_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR);khr_robustness_attribs.push_back(LOCAL_EGL_LOSE_CONTEXT_ON_RESET_KHR);khr_rbab_attribs=khr_robustness_attribs;khr_rbab_attribs.push_back(LOCAL_EGL_CONTEXT_FLAGS_KHR);khr_rbab_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);}}constautofnCreate=[&](conststd::vector<EGLint>&attribs){autoterminated_attribs=attribs;for(constauto&cur:kTerminationAttribs){terminated_attribs.push_back(cur);}returnegl->fCreateContext(contextConfig,EGL_NO_CONTEXT,terminated_attribs.data());};EGLContextcontext;do{if(!khr_rbab_attribs.empty()){context=fnCreate(khr_rbab_attribs);if(context)break;NS_WARNING("Failed to create EGLContext with khr_rbab_attribs");}if(!ext_rbab_attribs.empty()){context=fnCreate(ext_rbab_attribs);if(context)break;NS_WARNING("Failed to create EGLContext with ext_rbab_attribs");}if(!khr_robustness_attribs.empty()){context=fnCreate(khr_robustness_attribs);if(context)break;NS_WARNING("Failed to create EGLContext with khr_robustness_attribs");}if(!ext_robustness_attribs.empty()){context=fnCreate(ext_robustness_attribs);if(context)break;NS_WARNING("Failed to create EGLContext with ext_robustness_attribs");}context=fnCreate(required_attribs);if(context)break;NS_WARNING("Failed to create EGLContext with required_attribs");*out_failureId="FEATURE_FAILURE_EGL_CREATE"_ns;returnnullptr;}while(false);MOZ_ASSERT(context);RefPtr<GLContextEGL>glContext=newGLContextEGL(egl,desc,surfaceConfig,surface,context);if(!glContext->Init()){*out_failureId="FEATURE_FAILURE_EGL_INIT"_ns;returnnullptr;}if(GLContext::ShouldSpew()){printf_stderr("new GLContextEGL %p on EGLDisplay %p\n",glContext.get(),egl->mDisplay);}returnglContext;}// staticEGLSurfaceGLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(EglDisplay&egl,EGLConfigconfig,EGLenumbindToTextureFormat,mozilla::gfx::IntSize&pbsize){nsTArray<EGLint>pbattrs(16);EGLSurfacesurface=nullptr;TRY_AGAIN_POWER_OF_TWO:pbattrs.Clear();pbattrs.AppendElement(LOCAL_EGL_WIDTH);pbattrs.AppendElement(pbsize.width);pbattrs.AppendElement(LOCAL_EGL_HEIGHT);pbattrs.AppendElement(pbsize.height);if(bindToTextureFormat!=LOCAL_EGL_NONE){pbattrs.AppendElement(LOCAL_EGL_TEXTURE_TARGET);pbattrs.AppendElement(LOCAL_EGL_TEXTURE_2D);pbattrs.AppendElement(LOCAL_EGL_TEXTURE_FORMAT);pbattrs.AppendElement(bindToTextureFormat);}for(constauto&cur:kTerminationAttribs){pbattrs.AppendElement(cur);}surface=egl.fCreatePbufferSurface(config,&pbattrs[0]);if(!surface){if(!is_power_of_two(pbsize.width)||!is_power_of_two(pbsize.height)){if(!is_power_of_two(pbsize.width))pbsize.width=next_power_of_two(pbsize.width);if(!is_power_of_two(pbsize.height))pbsize.height=next_power_of_two(pbsize.height);NS_WARNING("Failed to create pbuffer, trying power of two dims");gotoTRY_AGAIN_POWER_OF_TWO;}NS_WARNING("Failed to create pbuffer surface");returnnullptr;}returnsurface;}#if defined(MOZ_WAYLAND)WaylandOffscreenGLSurface::WaylandOffscreenGLSurface(structwl_surface*aWaylandSurface,structwl_egl_window*aEGLWindow):mWaylandSurface(aWaylandSurface),mEGLWindow(aEGLWindow){}WaylandOffscreenGLSurface::~WaylandOffscreenGLSurface(){if(mEGLWindow){wl_egl_window_destroy(mEGLWindow);}if(mWaylandSurface){wl_surface_destroy(mWaylandSurface);}}// staticEGLSurfaceGLContextEGL::CreateWaylandOffscreenSurface(EglDisplay&egl,EGLConfigconfig,mozilla::gfx::IntSize&pbsize){wl_egl_window*eglwindow=nullptr;structwl_compositor*compositor=gdk_wayland_display_get_wl_compositor(gdk_display_get_default());structwl_surface*wlsurface=wl_compositor_create_surface(compositor);eglwindow=wl_egl_window_create(wlsurface,pbsize.width,pbsize.height);if(!eglwindow)returnnullptr;constautosurface=egl.fCreateWindowSurface(config,reinterpret_cast<EGLNativeWindowType>(eglwindow),0);if(surface){MOZ_DIAGNOSTIC_ASSERT(!sWaylandOffscreenGLSurfaces.Contains(surface));sWaylandOffscreenGLSurfaces.LookupOrInsert(surface,newWaylandOffscreenGLSurface(wlsurface,eglwindow));}returnsurface;}#endifstaticconstEGLintkEGLConfigAttribsRGB16[]={LOCAL_EGL_SURFACE_TYPE,LOCAL_EGL_WINDOW_BIT,LOCAL_EGL_RED_SIZE,5,LOCAL_EGL_GREEN_SIZE,6,LOCAL_EGL_BLUE_SIZE,5,LOCAL_EGL_ALPHA_SIZE,0};staticconstEGLintkEGLConfigAttribsRGB24[]={LOCAL_EGL_SURFACE_TYPE,LOCAL_EGL_WINDOW_BIT,LOCAL_EGL_RED_SIZE,8,LOCAL_EGL_GREEN_SIZE,8,LOCAL_EGL_BLUE_SIZE,8,LOCAL_EGL_ALPHA_SIZE,0};staticconstEGLintkEGLConfigAttribsRGBA32[]={LOCAL_EGL_SURFACE_TYPE,LOCAL_EGL_WINDOW_BIT,LOCAL_EGL_RED_SIZE,8,LOCAL_EGL_GREEN_SIZE,8,LOCAL_EGL_BLUE_SIZE,8,LOCAL_EGL_ALPHA_SIZE,8};boolCreateConfig(EglDisplay&aEgl,EGLConfig*aConfig,int32_taDepth,boolaEnableDepthBuffer,boolaUseGles,boolaAllowFallback){EGLConfigconfigs[64];std::vector<EGLint>attribs;EGLintncfg=std::size(configs);switch(aDepth){case16:for(constauto&cur:kEGLConfigAttribsRGB16){attribs.push_back(cur);}break;case24:for(constauto&cur:kEGLConfigAttribsRGB24){attribs.push_back(cur);}break;case32:for(constauto&cur:kEGLConfigAttribsRGBA32){attribs.push_back(cur);}break;default:NS_ERROR("Unknown pixel depth");returnfalse;}if(aUseGles){attribs.push_back(LOCAL_EGL_RENDERABLE_TYPE);attribs.push_back(LOCAL_EGL_OPENGL_ES2_BIT);}for(constauto&cur:kTerminationAttribs){attribs.push_back(cur);}if(!aEgl.fChooseConfig(attribs.data(),configs,ncfg,&ncfg)||ncfg<1){returnfalse;}Maybe<EGLConfig>fallbackConfig;for(intj=0;j<ncfg;++j){EGLConfigconfig=configs[j];EGLintr,g,b,a;if(aEgl.fGetConfigAttrib(config,LOCAL_EGL_RED_SIZE,&r)&&aEgl.fGetConfigAttrib(config,LOCAL_EGL_GREEN_SIZE,&g)&&aEgl.fGetConfigAttrib(config,LOCAL_EGL_BLUE_SIZE,&b)&&aEgl.fGetConfigAttrib(config,LOCAL_EGL_ALPHA_SIZE,&a)&&((aDepth==16&&r==5&&g==6&&b==5)||(aDepth==24&&r==8&&g==8&&b==8)||(aDepth==32&&r==8&&g==8&&b==8&&a==8))){EGLintz;if(aEnableDepthBuffer){if(!aEgl.fGetConfigAttrib(config,LOCAL_EGL_DEPTH_SIZE,&z)||z!=24){continue;}}#ifdef MOZ_X11if(GdkIsX11Display()){intconfigVisualID;if(!aEgl.fGetConfigAttrib(config,LOCAL_EGL_NATIVE_VISUAL_ID,&configVisualID)){continue;}XVisualInfovisual_info_template,*visual_info;intnum_visuals;visual_info_template.visualid=configVisualID;visual_info=XGetVisualInfo(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),VisualIDMask,&visual_info_template,&num_visuals);if(!visual_info||visual_info->depth!=aDepth){if(aAllowFallback&&!fallbackConfig){fallbackConfig=Some(config);}continue;}}#endif*aConfig=config;returntrue;}}if(kIsLinux&&fallbackConfig){*aConfig=fallbackConfig.value();returntrue;}returnfalse;}// Return true if a suitable EGLConfig was found and pass it out// through aConfig. Return false otherwise.//// NB: It's entirely legal for the returned EGLConfig to be valid yet// have the value null.staticboolCreateConfigScreen(EglDisplay&egl,EGLConfig*constaConfig,constboolaEnableDepthBuffer,constboolaUseGles){int32_tdepth=gfxVars::PrimaryScreenDepth();if(CreateConfig(egl,aConfig,depth,aEnableDepthBuffer,aUseGles)){returntrue;}#ifdef MOZ_WIDGET_ANDROID// Bug 736005// Android doesn't always support 16 bit so also try 24 bitif(depth==16){returnCreateConfig(egl,aConfig,24,aEnableDepthBuffer,aUseGles);}// Bug 970096// Some devices that have 24 bit screens only support 16 bit OpenGL?if(depth==24){returnCreateConfig(egl,aConfig,16,aEnableDepthBuffer,aUseGles);}#endifreturnfalse;}already_AddRefed<GLContext>GLContextProviderEGL::CreateForCompositorWidget(CompositorWidget*aCompositorWidget,boolaHardwareWebRender,bool/*aForceAccelerated*/){EGLNativeWindowTypewindow=nullptr;if(aCompositorWidget){window=GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aCompositorWidget);}returnGLContextEGLFactory::Create(window,aHardwareWebRender);}EGLSurfaceGLContextEGL::CreateCompatibleSurface(void*aWindow)const{MOZ_ASSERT(aWindow);MOZ_RELEASE_ASSERT(mSurfaceConfig!=EGL_NO_CONFIG);// NOTE: aWindow is an ANativeWindowEGLSurfacesurface=mEgl->fCreateWindowSurface(mSurfaceConfig,reinterpret_cast<EGLNativeWindowType>(aWindow),nullptr);if(!surface){gfxCriticalError()<<"CreateCompatibleSurface failed: "<<hexa(GetError());}returnsurface;}staticvoidFillContextAttribs(booles3,booluseGles,nsTArray<EGLint>*out){out->AppendElement(LOCAL_EGL_SURFACE_TYPE);#ifdef MOZ_WAYLANDif(GdkIsWaylandDisplay()){// Wayland on desktop does not support PBuffer or FBO.// We create a dummy wl_egl_window instead.out->AppendElement(LOCAL_EGL_WINDOW_BIT);}else#endif{out->AppendElement(LOCAL_EGL_PBUFFER_BIT);}if(useGles){out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);if(es3){out->AppendElement(LOCAL_EGL_OPENGL_ES3_BIT_KHR);}else{out->AppendElement(LOCAL_EGL_OPENGL_ES2_BIT);}}out->AppendElement(LOCAL_EGL_RED_SIZE);out->AppendElement(8);out->AppendElement(LOCAL_EGL_GREEN_SIZE);out->AppendElement(8);out->AppendElement(LOCAL_EGL_BLUE_SIZE);out->AppendElement(8);out->AppendElement(LOCAL_EGL_ALPHA_SIZE);out->AppendElement(8);out->AppendElement(LOCAL_EGL_DEPTH_SIZE);out->AppendElement(0);out->AppendElement(LOCAL_EGL_STENCIL_SIZE);out->AppendElement(0);// EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGSout->AppendElement(LOCAL_EGL_NONE);out->AppendElement(0);out->AppendElement(0);out->AppendElement(0);}/*/// Useful for debugging, but normally unused.static GLint GetAttrib(GLLibraryEGL* egl, EGLConfig config, EGLint attrib) { EGLint bits = 0; egl->fGetConfigAttrib(config, attrib, &bits); MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS); return bits;}*/staticEGLConfigChooseConfig(EglDisplay&egl,constGLContextCreateDesc&desc,constbooluseGles){nsTArray<EGLint>configAttribList;FillContextAttribs(bool(desc.flags&CreateContextFlags::PREFER_ES3),useGles,&configAttribList);constEGLint*configAttribs=configAttribList.Elements();// The sorting dictated by the spec for eglChooseConfig reasonably assures// that a reasonable 'best' config is on top.constEGLintkMaxConfigs=1;EGLConfigconfigs[kMaxConfigs];EGLintfoundConfigs=0;if(!egl.fChooseConfig(configAttribs,configs,kMaxConfigs,&foundConfigs)||foundConfigs==0){returnEGL_NO_CONFIG;}EGLConfigconfig=configs[0];returnconfig;}#ifdef MOZ_X11/* static */boolGLContextEGL::FindVisual(int*constout_visualId){nsCStringdiscardFailureId;constautoegl=DefaultEglDisplay(&discardFailureId);if(!egl){gfxCriticalNote<<"GLContextEGL::FindVisual(): Failed to load EGL library!";returnfalse;}EGLConfigconfig;constintbpp=32;if(!CreateConfig(*egl,&config,bpp,/* aEnableDepthBuffer */false,/* aUseGles */false,/* aAllowFallback */false)){// We are on a buggy driver. Do not return a visual so a fallback path can// be used. See https://gitlab.freedesktop.org/mesa/mesa/-/issues/149returnfalse;}if(egl->fGetConfigAttrib(config,LOCAL_EGL_NATIVE_VISUAL_ID,out_visualId)){returntrue;}returnfalse;}#endif/*static*/RefPtr<GLContextEGL>GLContextEGL::CreateWithoutSurface(conststd::shared_ptr<EglDisplay>egl,constGLContextCreateDesc&desc,nsACString*constout_failureId){constautoWithUseGles=[&](constbooluseGles)->RefPtr<GLContextEGL>{#ifdef MOZ_WIDGET_GTK// First try creating a context with no config and no surface, this is what// we really want, and seems to be the only way to make selecting software// Mesa init properly when it's not the first device.if(egl->IsExtensionSupported(EGLExtension::KHR_no_config_context)&&egl->IsExtensionSupported(EGLExtension::KHR_surfaceless_context)){// These extensions have been supported by mesa and nvidia drivers// since 2014 or earlier, this is the preferred code pathautofullDesc=GLContextDesc{desc};fullDesc.isOffscreen=true;RefPtr<GLContextEGL>gl=GLContextEGL::CreateGLContext(egl,fullDesc,EGL_NO_CONFIG,EGL_NO_SURFACE,useGles,EGL_NO_CONFIG,out_failureId);if(gl){returngl;}NS_WARNING("Failed to create GLContext with no config and no surface, will try ""ChooseConfig");}#endifconstEGLConfigsurfaceConfig=ChooseConfig(*egl,desc,useGles);if(surfaceConfig==EGL_NO_CONFIG){*out_failureId="FEATURE_FAILURE_EGL_NO_CONFIG"_ns;NS_WARNING("Failed to find a compatible config.");returnnullptr;}if(GLContext::ShouldSpew()){egl->DumpEGLConfig(surfaceConfig);}constEGLConfigcontextConfig=egl->IsExtensionSupported(EGLExtension::KHR_no_config_context)?nullptr:surfaceConfig;autodummySize=mozilla::gfx::IntSize{16,16};EGLSurfacesurface=nullptr;#ifdef MOZ_WAYLANDif(GdkIsWaylandDisplay()){surface=GLContextEGL::CreateWaylandOffscreenSurface(*egl,surfaceConfig,dummySize);}else#endif{surface=GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(*egl,surfaceConfig,LOCAL_EGL_NONE,dummySize);}if(!surface){*out_failureId="FEATURE_FAILURE_EGL_POT"_ns;NS_WARNING("Failed to create PBuffer for context!");returnnullptr;}autofullDesc=GLContextDesc{desc};fullDesc.isOffscreen=true;RefPtr<GLContextEGL>gl=GLContextEGL::CreateGLContext(egl,fullDesc,surfaceConfig,surface,useGles,contextConfig,out_failureId);if(!gl){NS_WARNING("Failed to create GLContext from PBuffer");egl->fDestroySurface(surface);#if defined(MOZ_WAYLAND)DeleteWaylandOffscreenGLSurface(surface);#endifreturnnullptr;}returngl;};boolpreferGles;#if defined(MOZ_WIDGET_ANDROID)preferGles=true;#elsepreferGles=StaticPrefs::gfx_egl_prefer_gles_enabled_AtStartup();#endif // defined(MOZ_WIDGET_ANDROID)RefPtr<GLContextEGL>gl=WithUseGles(preferGles);#if !defined(MOZ_WIDGET_ANDROID)if(!gl){gl=WithUseGles(!preferGles);}#endif // !defined(MOZ_WIDGET_ANDROID)returngl;}/*static*/voidGLContextEGL::DestroySurface(EglDisplay&aEgl,constEGLSurfaceaSurface){if(aSurface!=EGL_NO_SURFACE){if(!aEgl.fMakeCurrent(EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT)){constEGLinterr=aEgl.mLib->fGetError();gfxCriticalNote<<"Error in eglMakeCurrent: "<<gfx::hexa(err);}if(!aEgl.fDestroySurface(aSurface)){constEGLinterr=aEgl.mLib->fGetError();gfxCriticalNote<<"Error in eglDestroySurface: "<<gfx::hexa(err);}#if defined(MOZ_WAYLAND)DeleteWaylandOffscreenGLSurface(aSurface);#endif}}/*static*/already_AddRefed<GLContext>GLContextProviderEGL::CreateHeadless(constGLContextCreateDesc&desc,nsACString*constout_failureId){booluseSoftwareDisplay=static_cast<bool>(desc.flags&CreateContextFlags::FORBID_HARDWARE);constautodisplay=useSoftwareDisplay?CreateSoftwareEglDisplay(out_failureId):DefaultEglDisplay(out_failureId);if(!display){returnnullptr;}autoret=GLContextEGL::CreateWithoutSurface(display,desc,out_failureId);returnret.forget();}// Don't want a global context on Android as 1) share groups across 2 threads// fail on many Tegra drivers (bug 759225) and 2) some mobile devices have a// very strict limit on global number of GL contexts (bug 754257) and 3) each// EGL context eats 750k on B2G (bug 813783)/*static*/GLContext*GLContextProviderEGL::GetGlobalContext(){returnnullptr;}// -/*static*/voidGLContextProviderEGL::Shutdown(){GLLibraryEGL::Shutdown();}}/* namespace gl */}/* namespace mozilla */#undef EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS