GLContextProviderEAGL.mm (4596B)
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 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 #include "GLContextProvider.h" 7 #include "GLContextEAGL.h" 8 #include "GLLibraryLoader.h" 9 #include "nsDebug.h" 10 #include "nsIWidget.h" 11 #include "gfxFailure.h" 12 #include "prenv.h" 13 #include "mozilla/Preferences.h" 14 #include "mozilla/ProfilerLabels.h" 15 #include "mozilla/layers/CompositorOptions.h" 16 #include "mozilla/widget/CompositorWidget.h" 17 18 #import <UIKit/UIKit.h> 19 20 namespace mozilla { 21 namespace gl { 22 23 using namespace mozilla::widget; 24 25 GLContextEAGL::GLContextEAGL(const GLContextDesc& desc, EAGLContext* context, 26 GLContext* sharedContext) 27 : GLContext(desc, sharedContext), mContext(context) {} 28 29 GLContextEAGL::~GLContextEAGL() { 30 MakeCurrent(); 31 32 if (mBackbufferFB) { 33 fDeleteFramebuffers(1, &mBackbufferFB); 34 } 35 36 if (mBackbufferRB) { 37 fDeleteRenderbuffers(1, &mBackbufferRB); 38 } 39 40 MarkDestroyed(); 41 42 if (mContext) { 43 [EAGLContext setCurrentContext:nil]; 44 [mContext release]; 45 } 46 } 47 48 bool GLContextEAGL::MakeCurrentImpl() const { 49 if (mContext) { 50 GLContext::ResetTLSCurrentContext(); 51 52 if (![EAGLContext setCurrentContext:mContext]) { 53 return false; 54 } 55 } 56 return true; 57 } 58 59 bool GLContextEAGL::IsCurrentImpl() const { 60 return [EAGLContext currentContext] == mContext; 61 } 62 63 static PRFuncPtr GLAPIENTRY GetLoadedProcAddress(const char* const name) { 64 PRLibrary* lib = nullptr; 65 const auto& ret = PR_FindFunctionSymbolAndLibrary(name, &lib); 66 if (lib) { 67 PR_UnloadLibrary(lib); 68 } 69 return ret; 70 } 71 72 Maybe<SymbolLoader> GLContextEAGL::GetSymbolLoader() const { 73 return Some(SymbolLoader(&GetLoadedProcAddress)); 74 } 75 76 bool GLContextEAGL::IsDoubleBuffered() const { return true; } 77 78 bool GLContextEAGL::SwapBuffers() { 79 AUTO_PROFILER_LABEL("GLContextEAGL::SwapBuffers", GRAPHICS); 80 81 [mContext presentRenderbuffer:LOCAL_GL_RENDERBUFFER]; 82 return true; 83 } 84 85 void GLContextEAGL::GetWSIInfo(nsCString* const out) const { 86 out->AppendLiteral("EAGL"); 87 } 88 89 static GLContextEAGL* GetGlobalContextEAGL() { 90 return static_cast<GLContextEAGL*>(GLContextProviderEAGL::GetGlobalContext()); 91 } 92 93 static RefPtr<GLContext> CreateEAGLContext(const GLContextDesc& desc, 94 GLContextEAGL* sharedContext) { 95 EAGLRenderingAPI apis[] = {kEAGLRenderingAPIOpenGLES3, 96 kEAGLRenderingAPIOpenGLES2}; 97 98 // Try to create a GLES3 context if we can, otherwise fall back to GLES2 99 EAGLContext* context = nullptr; 100 for (EAGLRenderingAPI api : apis) { 101 if (sharedContext) { 102 context = [[EAGLContext alloc] 103 initWithAPI:api 104 sharegroup:sharedContext->GetEAGLContext().sharegroup]; 105 } else { 106 context = [[EAGLContext alloc] initWithAPI:api]; 107 } 108 109 if (context) { 110 break; 111 } 112 } 113 114 if (!context) { 115 return nullptr; 116 } 117 118 RefPtr<GLContextEAGL> glContext = 119 new GLContextEAGL(desc, context, sharedContext); 120 if (!glContext->Init()) { 121 glContext = nullptr; 122 return nullptr; 123 } 124 125 return glContext; 126 } 127 128 already_AddRefed<GLContext> GLContextProviderEAGL::CreateForCompositorWidget( 129 CompositorWidget* aCompositorWidget, bool aHardwareWebRender, 130 bool aForceAccelerated) { 131 CreateContextFlags flags = CreateContextFlags::ALLOW_OFFLINE_RENDERER; 132 if (aForceAccelerated) { 133 flags |= CreateContextFlags::FORBID_SOFTWARE; 134 } 135 nsCString failureUnused; 136 return CreateHeadless({flags}, &failureUnused); 137 } 138 139 already_AddRefed<GLContext> GLContextProviderEAGL::CreateHeadless( 140 const GLContextCreateDesc& createDesc, nsACString* const out_failureId) { 141 auto desc = GLContextDesc{createDesc}; 142 return CreateEAGLContext(desc, GetGlobalContextEAGL()).forget(); 143 } 144 145 constinit static RefPtr<GLContext> gGlobalContext; 146 147 GLContext* GLContextProviderEAGL::GetGlobalContext() { 148 static bool triedToCreateContext = false; 149 if (!triedToCreateContext) { 150 triedToCreateContext = true; 151 152 MOZ_RELEASE_ASSERT(!gGlobalContext, 153 "GFX: Global GL context already initialized."); 154 nsCString discardFailureId; 155 RefPtr<GLContext> temp = CreateHeadless({}, &discardFailureId); 156 gGlobalContext = temp; 157 158 if (!gGlobalContext) { 159 MOZ_CRASH("Failed to create global context"); 160 } 161 } 162 163 return gGlobalContext; 164 } 165 166 void GLContextProviderEAGL::Shutdown() { gGlobalContext = nullptr; } 167 168 } /* namespace gl */ 169 } /* namespace mozilla */