tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 */