LCOV - code coverage report
Current view: top level - gfx/gl - GLContextProviderGLX.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 3 450 0.7 %
Date: 2017-07-14 16:53:18 Functions: 2 40 5.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             : #ifdef MOZ_WIDGET_GTK
       7             : #include <gdk/gdk.h>
       8             : #include <gdk/gdkx.h>
       9             : #define GET_NATIVE_WINDOW(aWidget) GDK_WINDOW_XID((GdkWindow*) aWidget->GetNativeData(NS_NATIVE_WINDOW))
      10             : #endif
      11             : 
      12             : #include <X11/Xlib.h>
      13             : #include <X11/Xutil.h>
      14             : #include "X11UndefineNone.h"
      15             : 
      16             : #include "mozilla/MathAlgorithms.h"
      17             : #include "mozilla/StaticPtr.h"
      18             : #include "mozilla/layers/CompositorOptions.h"
      19             : #include "mozilla/widget/CompositorWidget.h"
      20             : #include "mozilla/widget/X11CompositorWidget.h"
      21             : #include "mozilla/Unused.h"
      22             : 
      23             : #include "prenv.h"
      24             : #include "GLContextProvider.h"
      25             : #include "GLLibraryLoader.h"
      26             : #include "nsDebug.h"
      27             : #include "nsIWidget.h"
      28             : #include "GLXLibrary.h"
      29             : #include "gfxXlibSurface.h"
      30             : #include "gfxContext.h"
      31             : #include "gfxEnv.h"
      32             : #include "gfxPlatform.h"
      33             : #include "GLContextGLX.h"
      34             : #include "gfxUtils.h"
      35             : #include "gfx2DGlue.h"
      36             : #include "GLScreenBuffer.h"
      37             : #include "gfxPrefs.h"
      38             : 
      39             : #include "gfxCrashReporterUtils.h"
      40             : 
      41             : #ifdef MOZ_WIDGET_GTK
      42             : #include "gfxPlatformGtk.h"
      43             : #endif
      44             : 
      45             : namespace mozilla {
      46             : namespace gl {
      47             : 
      48             : using namespace mozilla::gfx;
      49             : using namespace mozilla::widget;
      50             : 
      51           3 : GLXLibrary sGLXLibrary;
      52             : 
      53             : static inline bool
      54           0 : HasExtension(const char* aExtensions, const char* aRequiredExtension)
      55             : {
      56             :     return GLContext::ListHasExtension(
      57           0 :         reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
      58             : }
      59             : 
      60             : bool
      61           0 : GLXLibrary::EnsureInitialized()
      62             : {
      63           0 :     if (mInitialized) {
      64           0 :         return true;
      65             :     }
      66             : 
      67             :     // Don't repeatedly try to initialize.
      68           0 :     if (mTriedInitializing) {
      69           0 :         return false;
      70             :     }
      71           0 :     mTriedInitializing = true;
      72             : 
      73             :     // Force enabling s3 texture compression. (Bug 774134)
      74           0 :     PR_SetEnv("force_s3tc_enable=true");
      75             : 
      76           0 :     if (!mOGLLibrary) {
      77           0 :         const char* libGLfilename = nullptr;
      78           0 :         bool forceFeatureReport = false;
      79             : 
      80             :         // see e.g. bug 608526: it is intrinsically interesting to know whether we have dynamically linked to libGL.so.1
      81             :         // because at least the NVIDIA implementation requires an executable stack, which causes mprotect calls,
      82             :         // which trigger glibc bug http://sourceware.org/bugzilla/show_bug.cgi?id=12225
      83             : #ifdef __OpenBSD__
      84             :         libGLfilename = "libGL.so";
      85             : #else
      86           0 :         libGLfilename = "libGL.so.1";
      87             : #endif
      88             : 
      89           0 :         ScopedGfxFeatureReporter reporter(libGLfilename, forceFeatureReport);
      90           0 :         mOGLLibrary = PR_LoadLibrary(libGLfilename);
      91           0 :         if (!mOGLLibrary) {
      92           0 :             NS_WARNING("Couldn't load OpenGL shared library.");
      93           0 :             return false;
      94             :         }
      95           0 :         reporter.SetSuccessful();
      96             :     }
      97             : 
      98           0 :     if (gfxEnv::GlxDebug()) {
      99           0 :         mDebug = true;
     100             :     }
     101             : 
     102             : #define SYMBOL(X) { (PRFuncPtr*)&mSymbols.f##X, { "glX" #X, nullptr } }
     103             : #define END_OF_SYMBOLS { nullptr, { nullptr } }
     104             : 
     105             :     const GLLibraryLoader::SymLoadStruct symbols[] = {
     106             :         /* functions that were in GLX 1.0 */
     107           0 :         SYMBOL(DestroyContext),
     108           0 :         SYMBOL(MakeCurrent),
     109           0 :         SYMBOL(SwapBuffers),
     110           0 :         SYMBOL(QueryVersion),
     111           0 :         SYMBOL(GetCurrentContext),
     112           0 :         SYMBOL(WaitGL),
     113           0 :         SYMBOL(WaitX),
     114             : 
     115             :         /* functions introduced in GLX 1.1 */
     116           0 :         SYMBOL(QueryExtensionsString),
     117           0 :         SYMBOL(GetClientString),
     118           0 :         SYMBOL(QueryServerString),
     119             : 
     120             :         /* functions introduced in GLX 1.3 */
     121           0 :         SYMBOL(ChooseFBConfig),
     122           0 :         SYMBOL(GetFBConfigAttrib),
     123           0 :         SYMBOL(GetFBConfigs),
     124           0 :         SYMBOL(CreatePixmap),
     125           0 :         SYMBOL(DestroyPixmap),
     126           0 :         SYMBOL(CreateNewContext),
     127             : 
     128             :         // Core in GLX 1.4, ARB extension before.
     129           0 :         { (PRFuncPtr*)&mSymbols.fGetProcAddress, { "glXGetProcAddress",
     130             :                                                    "glXGetProcAddressARB",
     131             :                                                    nullptr } },
     132             :         END_OF_SYMBOLS
     133           0 :     };
     134           0 :     if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols)) {
     135           0 :         NS_WARNING("Couldn't load required GLX symbols.");
     136           0 :         return false;
     137             :     }
     138             : 
     139           0 :     Display* display = DefaultXDisplay();
     140           0 :     int screen = DefaultScreen(display);
     141             : 
     142             :     {
     143             :         int major, minor;
     144           0 :         if (!fQueryVersion(display, &major, &minor) ||
     145           0 :             major != 1 || minor < 3)
     146             :         {
     147           0 :             NS_ERROR("GLX version older than 1.3. (released in 1998)");
     148           0 :             return false;
     149             :         }
     150             :     }
     151             : 
     152             :     const GLLibraryLoader::SymLoadStruct symbols_texturefrompixmap[] = {
     153           0 :         SYMBOL(BindTexImageEXT),
     154           0 :         SYMBOL(ReleaseTexImageEXT),
     155             :         END_OF_SYMBOLS
     156           0 :     };
     157             : 
     158             :     const GLLibraryLoader::SymLoadStruct symbols_createcontext[] = {
     159           0 :         SYMBOL(CreateContextAttribsARB),
     160             :         END_OF_SYMBOLS
     161           0 :     };
     162             : 
     163             :     const GLLibraryLoader::SymLoadStruct symbols_videosync[] = {
     164           0 :         SYMBOL(GetVideoSyncSGI),
     165           0 :         SYMBOL(WaitVideoSyncSGI),
     166             :         END_OF_SYMBOLS
     167           0 :     };
     168             : 
     169             :     const GLLibraryLoader::SymLoadStruct symbols_swapcontrol[] = {
     170           0 :         SYMBOL(SwapIntervalEXT),
     171             :         END_OF_SYMBOLS
     172           0 :     };
     173             : 
     174             :     const auto lookupFunction =
     175           0 :         (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress;
     176             : 
     177           0 :     const auto fnLoadSymbols = [&](const GLLibraryLoader::SymLoadStruct* symbols) {
     178           0 :         if (GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols, lookupFunction))
     179           0 :             return true;
     180             : 
     181           0 :         GLLibraryLoader::ClearSymbols(symbols);
     182           0 :         return false;
     183           0 :     };
     184             : 
     185           0 :     const char* clientVendor = fGetClientString(display, LOCAL_GLX_VENDOR);
     186           0 :     const char* serverVendor = fQueryServerString(display, screen, LOCAL_GLX_VENDOR);
     187           0 :     const char* extensionsStr = fQueryExtensionsString(display, screen);
     188             : 
     189           0 :     if (HasExtension(extensionsStr, "GLX_EXT_texture_from_pixmap") &&
     190           0 :         fnLoadSymbols(symbols_texturefrompixmap))
     191             :     {
     192           0 :         mUseTextureFromPixmap = gfxPrefs::UseGLXTextureFromPixmap();
     193             :     } else {
     194           0 :         mUseTextureFromPixmap = false;
     195           0 :         NS_WARNING("Texture from pixmap disabled");
     196             :     }
     197             : 
     198           0 :     if (HasExtension(extensionsStr, "GLX_ARB_create_context") &&
     199           0 :         HasExtension(extensionsStr, "GLX_ARB_create_context_profile") &&
     200           0 :         fnLoadSymbols(symbols_createcontext))
     201             :     {
     202           0 :         mHasCreateContextAttribs = true;
     203             :     }
     204             : 
     205           0 :     if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness")) {
     206           0 :         mHasRobustness = true;
     207             :     }
     208             : 
     209           0 :     if (HasExtension(extensionsStr, "GLX_SGI_video_sync") &&
     210           0 :         fnLoadSymbols(symbols_videosync))
     211             :     {
     212           0 :         mHasVideoSync = true;
     213             :     }
     214             : 
     215           0 :     if (!HasExtension(extensionsStr, "GLX_EXT_swap_control") ||
     216           0 :         !fnLoadSymbols(symbols_swapcontrol))
     217             :     {
     218           0 :         NS_WARNING("GLX_swap_control unsupported, ASAP mode may still block on buffer swaps.");
     219             :     }
     220             : 
     221           0 :     mIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
     222           0 :     mIsNVIDIA = serverVendor && DoesStringMatch(serverVendor, "NVIDIA Corporation");
     223           0 :     mClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa");
     224             : 
     225           0 :     mInitialized = true;
     226             : 
     227           0 :     return true;
     228             : }
     229             : 
     230             : bool
     231           0 : GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface)
     232             : {
     233           0 :     if (!EnsureInitialized()) {
     234           0 :         return false;
     235             :     }
     236             : 
     237           0 :     if (aSurface->GetType() != gfxSurfaceType::Xlib || !mUseTextureFromPixmap) {
     238           0 :         return false;
     239             :     }
     240             : 
     241           0 :     return true;
     242             : }
     243             : 
     244             : bool
     245           0 : GLXLibrary::SupportsVideoSync()
     246             : {
     247           0 :     if (!EnsureInitialized()) {
     248           0 :         return false;
     249             :     }
     250             : 
     251           0 :     return mHasVideoSync;
     252             : }
     253             : 
     254             : GLXPixmap
     255           0 : GLXLibrary::CreatePixmap(gfxASurface* aSurface)
     256             : {
     257           0 :     if (!SupportsTextureFromPixmap(aSurface)) {
     258           0 :         return X11None;
     259             :     }
     260             : 
     261           0 :     gfxXlibSurface* xs = static_cast<gfxXlibSurface*>(aSurface);
     262           0 :     const XRenderPictFormat* format = xs->XRenderFormat();
     263           0 :     if (!format || format->type != PictTypeDirect) {
     264           0 :         return X11None;
     265             :     }
     266           0 :     const XRenderDirectFormat& direct = format->direct;
     267           0 :     int alphaSize = FloorLog2(direct.alphaMask + 1);
     268           0 :     NS_ASSERTION((1 << alphaSize) - 1 == direct.alphaMask,
     269             :                  "Unexpected render format with non-adjacent alpha bits");
     270             : 
     271             :     int attribs[] = { LOCAL_GLX_DOUBLEBUFFER, False,
     272             :                       LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT,
     273             :                       LOCAL_GLX_ALPHA_SIZE, alphaSize,
     274           0 :                       (alphaSize ? LOCAL_GLX_BIND_TO_TEXTURE_RGBA_EXT
     275             :                        : LOCAL_GLX_BIND_TO_TEXTURE_RGB_EXT), True,
     276             :                       LOCAL_GLX_RENDER_TYPE, LOCAL_GLX_RGBA_BIT,
     277           0 :                       X11None };
     278             : 
     279           0 :     int numConfigs = 0;
     280           0 :     Display* display = xs->XDisplay();
     281           0 :     int xscreen = DefaultScreen(display);
     282             : 
     283             :     ScopedXFree<GLXFBConfig> cfgs(fChooseFBConfig(display,
     284             :                                                   xscreen,
     285             :                                                   attribs,
     286           0 :                                                   &numConfigs));
     287             : 
     288             :     // Find an fbconfig that matches the pixel format used on the Pixmap.
     289           0 :     int matchIndex = -1;
     290             :     unsigned long redMask =
     291           0 :         static_cast<unsigned long>(direct.redMask) << direct.red;
     292             :     unsigned long greenMask =
     293           0 :         static_cast<unsigned long>(direct.greenMask) << direct.green;
     294             :     unsigned long blueMask =
     295           0 :         static_cast<unsigned long>(direct.blueMask) << direct.blue;
     296             :     // This is true if the Pixmap has bits for alpha or unused bits.
     297             :     bool haveNonColorBits =
     298           0 :         ~(redMask | greenMask | blueMask) != -1UL << format->depth;
     299             : 
     300           0 :     for (int i = 0; i < numConfigs; i++) {
     301           0 :         int id = X11None;
     302           0 :         sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &id);
     303             :         Visual* visual;
     304             :         int depth;
     305           0 :         FindVisualAndDepth(display, id, &visual, &depth);
     306           0 :         if (!visual ||
     307           0 :             visual->c_class != TrueColor ||
     308           0 :             visual->red_mask != redMask ||
     309           0 :             visual->green_mask != greenMask ||
     310           0 :             visual->blue_mask != blueMask ) {
     311           0 :             continue;
     312             :         }
     313             : 
     314             :         // Historically Xlib Visuals did not try to represent an alpha channel
     315             :         // and there was no means to use an alpha channel on a Pixmap.  The
     316             :         // Xlib Visual from the fbconfig was not intended to have any
     317             :         // information about alpha bits.
     318             :         //
     319             :         // Since then, RENDER has added formats for 32 bit depth Pixmaps.
     320             :         // Some of these formats have bits for alpha and some have unused
     321             :         // bits.
     322             :         //
     323             :         // Then the Composite extension added a 32 bit depth Visual intended
     324             :         // for Windows with an alpha channel, so bits not in the visual color
     325             :         // masks were expected to be treated as alpha bits.
     326             :         //
     327             :         // Usually GLX counts only color bits in the Visual depth, but the
     328             :         // depth of Composite's ARGB Visual includes alpha bits.  However,
     329             :         // bits not in the color masks are not necessarily alpha bits because
     330             :         // sometimes (NVIDIA) 32 bit Visuals are added for fbconfigs with 32
     331             :         // bit BUFFER_SIZE but zero alpha bits and 24 color bits (NVIDIA
     332             :         // again).
     333             :         //
     334             :         // This checks that the depth matches in one of the two ways.
     335             :         // NVIDIA now forces format->depth == depth so only the first way
     336             :         // is checked for NVIDIA
     337           0 :         if (depth != format->depth &&
     338           0 :             (mIsNVIDIA || depth != format->depth - alphaSize) ) {
     339           0 :             continue;
     340             :         }
     341             : 
     342             :         // If all bits of the Pixmap are color bits and the Pixmap depth
     343             :         // matches the depth of the fbconfig visual, then we can assume that
     344             :         // the driver will do whatever is necessary to ensure that any
     345             :         // GLXPixmap alpha bits are treated as set.  We can skip the
     346             :         // ALPHA_SIZE check in this situation.  We need to skip this check for
     347             :         // situations (ATI) where there are no fbconfigs without alpha bits.
     348             :         //
     349             :         // glXChooseFBConfig should prefer configs with smaller
     350             :         // LOCAL_GLX_BUFFER_SIZE, so we should still get zero alpha bits if
     351             :         // available, except perhaps with NVIDIA drivers where buffer size is
     352             :         // not the specified sum of the component sizes.
     353           0 :         if (haveNonColorBits) {
     354             :             // There are bits in the Pixmap format that haven't been matched
     355             :             // against the fbconfig visual.  These bits could either represent
     356             :             // alpha or be unused, so just check that the number of alpha bits
     357             :             // matches.
     358           0 :             int size = 0;
     359           0 :             sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i],
     360           0 :                                            LOCAL_GLX_ALPHA_SIZE, &size);
     361           0 :             if (size != alphaSize) {
     362           0 :                 continue;
     363             :             }
     364             :         }
     365             : 
     366           0 :         matchIndex = i;
     367           0 :         break;
     368             :     }
     369           0 :     if (matchIndex == -1) {
     370             :         // GLX can't handle A8 surfaces, so this is not really unexpected. The
     371             :         // caller should deal with this situation.
     372           0 :         NS_WARNING_ASSERTION(
     373             :           format->depth == 8,
     374             :           "[GLX] Couldn't find a FBConfig matching Pixmap format");
     375           0 :         return X11None;
     376             :     }
     377             : 
     378             :     int pixmapAttribs[] = { LOCAL_GLX_TEXTURE_TARGET_EXT, LOCAL_GLX_TEXTURE_2D_EXT,
     379             :                             LOCAL_GLX_TEXTURE_FORMAT_EXT,
     380           0 :                             (alphaSize ? LOCAL_GLX_TEXTURE_FORMAT_RGBA_EXT
     381             :                              : LOCAL_GLX_TEXTURE_FORMAT_RGB_EXT),
     382           0 :                             X11None};
     383             : 
     384           0 :     GLXPixmap glxpixmap = fCreatePixmap(display,
     385           0 :                                         cfgs[matchIndex],
     386             :                                         xs->XDrawable(),
     387           0 :                                         pixmapAttribs);
     388             : 
     389           0 :     return glxpixmap;
     390             : }
     391             : 
     392             : void
     393           0 : GLXLibrary::DestroyPixmap(Display* aDisplay, GLXPixmap aPixmap)
     394             : {
     395           0 :     if (!mUseTextureFromPixmap) {
     396           0 :         return;
     397             :     }
     398             : 
     399           0 :     fDestroyPixmap(aDisplay, aPixmap);
     400             : }
     401             : 
     402             : void
     403           0 : GLXLibrary::BindTexImage(Display* aDisplay, GLXPixmap aPixmap)
     404             : {
     405           0 :     if (!mUseTextureFromPixmap) {
     406           0 :         return;
     407             :     }
     408             : 
     409             :     // Make sure all X drawing to the surface has finished before binding to a texture.
     410           0 :     if (mClientIsMesa) {
     411             :         // Using XSync instead of Mesa's glXWaitX, because its glxWaitX is a
     412             :         // noop when direct rendering unless the current drawable is a
     413             :         // single-buffer window.
     414           0 :         FinishX(aDisplay);
     415             :     } else {
     416           0 :         fWaitX();
     417             :     }
     418           0 :     fBindTexImage(aDisplay, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT, nullptr);
     419             : }
     420             : 
     421             : void
     422           0 : GLXLibrary::ReleaseTexImage(Display* aDisplay, GLXPixmap aPixmap)
     423             : {
     424           0 :     if (!mUseTextureFromPixmap) {
     425           0 :         return;
     426             :     }
     427             : 
     428           0 :     fReleaseTexImage(aDisplay, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT);
     429             : }
     430             : 
     431             : void
     432           0 : GLXLibrary::UpdateTexImage(Display* aDisplay, GLXPixmap aPixmap)
     433             : {
     434             :     // NVIDIA drivers don't require a rebind of the pixmap in order
     435             :     // to display an updated image, and it's faster not to do it.
     436           0 :     if (mIsNVIDIA) {
     437           0 :         fWaitX();
     438           0 :         return;
     439             :     }
     440             : 
     441           0 :     ReleaseTexImage(aDisplay, aPixmap);
     442           0 :     BindTexImage(aDisplay, aPixmap);
     443             : }
     444             : 
     445             : static int (*sOldErrorHandler)(Display*, XErrorEvent*);
     446           3 : ScopedXErrorHandler::ErrorEvent sErrorEvent;
     447           0 : static int GLXErrorHandler(Display* display, XErrorEvent* ev)
     448             : {
     449           0 :     if (!sErrorEvent.mError.error_code) {
     450           0 :         sErrorEvent.mError = *ev;
     451             :     }
     452           0 :     return 0;
     453             : }
     454             : 
     455             : void
     456           0 : GLXLibrary::BeforeGLXCall() const
     457             : {
     458           0 :     if (mDebug) {
     459           0 :         sOldErrorHandler = XSetErrorHandler(GLXErrorHandler);
     460             :     }
     461           0 : }
     462             : 
     463             : void
     464           0 : GLXLibrary::AfterGLXCall() const
     465             : {
     466           0 :     if (mDebug) {
     467           0 :         FinishX(DefaultXDisplay());
     468           0 :         if (sErrorEvent.mError.error_code) {
     469             :             char buffer[2048];
     470           0 :             XGetErrorText(DefaultXDisplay(), sErrorEvent.mError.error_code, buffer, sizeof(buffer));
     471           0 :             printf_stderr("X ERROR: %s (%i) - Request: %i.%i, Serial: %lu",
     472             :                           buffer,
     473           0 :                           sErrorEvent.mError.error_code,
     474           0 :                           sErrorEvent.mError.request_code,
     475           0 :                           sErrorEvent.mError.minor_code,
     476           0 :                           sErrorEvent.mError.serial);
     477           0 :             NS_ABORT();
     478             :         }
     479           0 :         XSetErrorHandler(sOldErrorHandler);
     480             :     }
     481           0 : }
     482             : 
     483             : already_AddRefed<GLContextGLX>
     484           0 : GLContextGLX::CreateGLContext(CreateContextFlags flags, const SurfaceCaps& caps,
     485             :                               bool isOffscreen, Display* display, GLXDrawable drawable,
     486             :                               GLXFBConfig cfg, bool deleteDrawable,
     487             :                               gfxXlibSurface* pixmap)
     488             : {
     489           0 :     GLXLibrary& glx = sGLXLibrary;
     490             : 
     491           0 :     int db = 0;
     492             :     int err = glx.fGetFBConfigAttrib(display, cfg,
     493           0 :                                       LOCAL_GLX_DOUBLEBUFFER, &db);
     494           0 :     if (LOCAL_GLX_BAD_ATTRIBUTE != err) {
     495           0 :         if (ShouldSpew()) {
     496           0 :             printf("[GLX] FBConfig is %sdouble-buffered\n", db ? "" : "not ");
     497             :         }
     498             :     }
     499             : 
     500             :     GLXContext context;
     501           0 :     RefPtr<GLContextGLX> glContext;
     502             :     bool error;
     503             : 
     504           0 :     OffMainThreadScopedXErrorHandler xErrorHandler;
     505             : 
     506             :     do {
     507           0 :         error = false;
     508             : 
     509           0 :         if (glx.HasCreateContextAttribs()) {
     510           0 :             AutoTArray<int, 11> attrib_list;
     511           0 :             if (glx.HasRobustness()) {
     512             :                 const int robust_attribs[] = {
     513             :                     LOCAL_GLX_CONTEXT_FLAGS_ARB,
     514             :                     LOCAL_GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB,
     515             :                     LOCAL_GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
     516             :                     LOCAL_GLX_LOSE_CONTEXT_ON_RESET_ARB,
     517           0 :                 };
     518           0 :                 attrib_list.AppendElements(robust_attribs, MOZ_ARRAY_LENGTH(robust_attribs));
     519             :             }
     520           0 :             if (!(flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE)) {
     521             :                 int core_attribs[] = {
     522             :                     LOCAL_GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
     523             :                     LOCAL_GLX_CONTEXT_MINOR_VERSION_ARB, 2,
     524             :                     LOCAL_GLX_CONTEXT_PROFILE_MASK_ARB, LOCAL_GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
     525           0 :                 };
     526           0 :                 attrib_list.AppendElements(core_attribs, MOZ_ARRAY_LENGTH(core_attribs));
     527             :             };
     528           0 :             attrib_list.AppendElement(0);
     529             : 
     530             :             context = glx.fCreateContextAttribs(
     531             :                 display,
     532             :                 cfg,
     533             :                 nullptr,
     534             :                 True,
     535           0 :                 attrib_list.Elements());
     536             :         } else {
     537             :             context = glx.fCreateNewContext(
     538             :                 display,
     539             :                 cfg,
     540             :                 LOCAL_GLX_RGBA_TYPE,
     541             :                 nullptr,
     542           0 :                 True);
     543             :         }
     544             : 
     545           0 :         if (context) {
     546             :             glContext = new GLContextGLX(flags, caps, isOffscreen, display, drawable,
     547           0 :                                          context, deleteDrawable, db, pixmap);
     548           0 :             if (!glContext->Init())
     549           0 :                 error = true;
     550             :         } else {
     551           0 :             error = true;
     552             :         }
     553             : 
     554           0 :         error |= xErrorHandler.SyncAndGetError(display);
     555             : 
     556           0 :         if (error) {
     557           0 :             NS_WARNING("Failed to create GLXContext!");
     558           0 :             glContext = nullptr; // note: this must be done while the graceful X error handler is set,
     559             :                                 // because glxMakeCurrent can give a GLXBadDrawable error
     560             :         }
     561             : 
     562           0 :         return glContext.forget();
     563             :     } while (true);
     564             : }
     565             : 
     566           0 : GLContextGLX::~GLContextGLX()
     567             : {
     568           0 :     MarkDestroyed();
     569             : 
     570             :     // Wrapped context should not destroy glxContext/Surface
     571           0 :     if (!mOwnsContext) {
     572           0 :         return;
     573             :     }
     574             : 
     575             :     // see bug 659842 comment 76
     576             : #ifdef DEBUG
     577             :     bool success =
     578             : #endif
     579           0 :     mGLX->fMakeCurrent(mDisplay, X11None, nullptr);
     580           0 :     MOZ_ASSERT(success,
     581             :                "glXMakeCurrent failed to release GL context before we call "
     582             :                "glXDestroyContext!");
     583             : 
     584           0 :     mGLX->fDestroyContext(mDisplay, mContext);
     585             : 
     586           0 :     if (mDeleteDrawable) {
     587           0 :         mGLX->fDestroyPixmap(mDisplay, mDrawable);
     588             :     }
     589           0 : }
     590             : 
     591             : 
     592             : bool
     593           0 : GLContextGLX::Init()
     594             : {
     595           0 :     SetupLookupFunction();
     596           0 :     if (!InitWithPrefix("gl", true)) {
     597           0 :         return false;
     598             :     }
     599             : 
     600             :     // EXT_framebuffer_object is not supported on Core contexts
     601             :     // so we'll also check for ARB_framebuffer_object
     602           0 :     if (!IsExtensionSupported(EXT_framebuffer_object) && !IsSupported(GLFeature::framebuffer_object))
     603           0 :         return false;
     604             : 
     605           0 :     return true;
     606             : }
     607             : 
     608             : bool
     609           0 : GLContextGLX::MakeCurrentImpl(bool aForce)
     610             : {
     611           0 :     bool succeeded = true;
     612             : 
     613             :     // With the ATI FGLRX driver, glxMakeCurrent is very slow even when the context doesn't change.
     614             :     // (This is not the case with other drivers such as NVIDIA).
     615             :     // So avoid calling it more than necessary. Since GLX documentation says that:
     616             :     //     "glXGetCurrentContext returns client-side information.
     617             :     //      It does not make a round trip to the server."
     618             :     // I assume that it's not worth using our own TLS slot here.
     619           0 :     if (aForce || mGLX->fGetCurrentContext() != mContext) {
     620           0 :         if (mGLX->IsMesa()) {
     621             :           // Read into the event queue to ensure that Mesa receives a
     622             :           // DRI2InvalidateBuffers event before drawing. See bug 1280653.
     623           0 :           Unused << XPending(mDisplay);
     624             :         }
     625             : 
     626           0 :         succeeded = mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
     627           0 :         NS_ASSERTION(succeeded, "Failed to make GL context current!");
     628             : 
     629           0 :         if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
     630             :             // Many GLX implementations default to blocking until the next
     631             :             // VBlank when calling glXSwapBuffers. We want to run unthrottled
     632             :             // in ASAP mode. See bug 1280744.
     633           0 :             const bool isASAP = (gfxPrefs::LayoutFrameRate() == 0);
     634           0 :             mGLX->fSwapInterval(mDisplay, mDrawable, isASAP ? 0 : 1);
     635             :         }
     636             :     }
     637             : 
     638           0 :     return succeeded;
     639             : }
     640             : 
     641             : bool
     642           0 : GLContextGLX::IsCurrent() {
     643           0 :     return mGLX->fGetCurrentContext() == mContext;
     644             : }
     645             : 
     646             : bool
     647           0 : GLContextGLX::SetupLookupFunction()
     648             : {
     649           0 :     mLookupFunc = (PlatformLookupFunction)sGLXLibrary.GetGetProcAddress();
     650           0 :     return true;
     651             : }
     652             : 
     653             : bool
     654           0 : GLContextGLX::IsDoubleBuffered() const
     655             : {
     656           0 :     return mDoubleBuffered;
     657             : }
     658             : 
     659             : bool
     660           0 : GLContextGLX::SwapBuffers()
     661             : {
     662           0 :     if (!mDoubleBuffered)
     663           0 :         return false;
     664           0 :     mGLX->fSwapBuffers(mDisplay, mDrawable);
     665           0 :     return true;
     666             : }
     667             : 
     668             : void
     669           0 : GLContextGLX::GetWSIInfo(nsCString* const out) const
     670             : {
     671           0 :     Display* display = DefaultXDisplay();
     672           0 :     int screen = DefaultScreen(display);
     673             : 
     674             :     int majorVersion, minorVersion;
     675           0 :     sGLXLibrary.fQueryVersion(display, &majorVersion, &minorVersion);
     676             : 
     677           0 :     out->Append(nsPrintfCString("GLX %u.%u", majorVersion, minorVersion));
     678             : 
     679           0 :     out->AppendLiteral("\nGLX_VENDOR(client): ");
     680           0 :     out->Append(sGLXLibrary.fGetClientString(display, LOCAL_GLX_VENDOR));
     681             : 
     682           0 :     out->AppendLiteral("\nGLX_VENDOR(server): ");
     683           0 :     out->Append(sGLXLibrary.fQueryServerString(display, screen, LOCAL_GLX_VENDOR));
     684             : 
     685           0 :     out->AppendLiteral("\nExtensions: ");
     686           0 :     out->Append(sGLXLibrary.fQueryExtensionsString(display, screen));
     687           0 : }
     688             : 
     689             : bool
     690           0 : GLContextGLX::OverrideDrawable(GLXDrawable drawable)
     691             : {
     692           0 :     if (Screen())
     693           0 :         Screen()->AssureBlitted();
     694           0 :     Bool result = mGLX->fMakeCurrent(mDisplay, drawable, mContext);
     695           0 :     return result;
     696             : }
     697             : 
     698             : bool
     699           0 : GLContextGLX::RestoreDrawable()
     700             : {
     701           0 :     return mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
     702             : }
     703             : 
     704           0 : GLContextGLX::GLContextGLX(
     705             :                   CreateContextFlags flags,
     706             :                   const SurfaceCaps& caps,
     707             :                   bool isOffscreen,
     708             :                   Display* aDisplay,
     709             :                   GLXDrawable aDrawable,
     710             :                   GLXContext aContext,
     711             :                   bool aDeleteDrawable,
     712             :                   bool aDoubleBuffered,
     713           0 :                   gfxXlibSurface* aPixmap)
     714             :     : GLContext(flags, caps, nullptr, isOffscreen),
     715             :       mContext(aContext),
     716             :       mDisplay(aDisplay),
     717             :       mDrawable(aDrawable),
     718             :       mDeleteDrawable(aDeleteDrawable),
     719             :       mDoubleBuffered(aDoubleBuffered),
     720             :       mGLX(&sGLXLibrary),
     721             :       mPixmap(aPixmap),
     722           0 :       mOwnsContext(true)
     723             : {
     724           0 : }
     725             : 
     726             : static bool
     727           0 : AreCompatibleVisuals(Visual* one, Visual* two)
     728             : {
     729           0 :     if (one->c_class != two->c_class) {
     730           0 :         return false;
     731             :     }
     732             : 
     733           0 :     if (one->red_mask != two->red_mask ||
     734           0 :         one->green_mask != two->green_mask ||
     735           0 :         one->blue_mask != two->blue_mask) {
     736           0 :         return false;
     737             :     }
     738             : 
     739           0 :     if (one->bits_per_rgb != two->bits_per_rgb) {
     740           0 :         return false;
     741             :     }
     742             : 
     743           0 :     return true;
     744             : }
     745             : 
     746             : already_AddRefed<GLContext>
     747           0 : GLContextProviderGLX::CreateWrappingExisting(void* aContext, void* aSurface)
     748             : {
     749           0 :     if (!sGLXLibrary.EnsureInitialized()) {
     750           0 :         return nullptr;
     751             :     }
     752             : 
     753           0 :     if (aContext && aSurface) {
     754           0 :         SurfaceCaps caps = SurfaceCaps::Any();
     755             :         RefPtr<GLContextGLX> glContext =
     756             :             new GLContextGLX(CreateContextFlags::NONE, caps,
     757             :                              false, // Offscreen
     758           0 :                              (Display*)DefaultXDisplay(), // Display
     759             :                              (GLXDrawable)aSurface, (GLXContext)aContext,
     760             :                              false, // aDeleteDrawable,
     761             :                              true,
     762           0 :                              (gfxXlibSurface*)nullptr);
     763             : 
     764           0 :         glContext->mOwnsContext = false;
     765           0 :         return glContext.forget();
     766             :     }
     767             : 
     768           0 :     return nullptr;
     769             : }
     770             : 
     771             : already_AddRefed<GLContext>
     772           0 : CreateForWidget(Display* aXDisplay, Window aXWindow,
     773             :                 bool aWebRender,
     774             :                 bool aForceAccelerated)
     775             : {
     776           0 :     if (!sGLXLibrary.EnsureInitialized()) {
     777           0 :         return nullptr;
     778             :     }
     779             : 
     780             :     // Currently, we take whatever Visual the window already has, and
     781             :     // try to create an fbconfig for that visual.  This isn't
     782             :     // necessarily what we want in the long run; an fbconfig may not
     783             :     // be available for the existing visual, or if it is, the GL
     784             :     // performance might be suboptimal.  But using the existing visual
     785             :     // is a relatively safe intermediate step.
     786             : 
     787           0 :     if (!aXDisplay) {
     788           0 :         NS_ERROR("X Display required for GLX Context provider");
     789           0 :         return nullptr;
     790             :     }
     791             : 
     792           0 :     int xscreen = DefaultScreen(aXDisplay);
     793             : 
     794           0 :     ScopedXFree<GLXFBConfig> cfgs;
     795             :     GLXFBConfig config;
     796             :     int visid;
     797           0 :     if (!GLContextGLX::FindFBConfigForWindow(aXDisplay, xscreen, aXWindow, &cfgs,
     798             :                                              &config, &visid, aWebRender))
     799             :     {
     800           0 :         return nullptr;
     801             :     }
     802             : 
     803             :     CreateContextFlags flags;
     804           0 :     if (aWebRender) {
     805           0 :         flags = CreateContextFlags::NONE; // WR needs GL3.2+
     806             :     } else {
     807           0 :         flags = CreateContextFlags::REQUIRE_COMPAT_PROFILE;
     808             :     }
     809           0 :     return GLContextGLX::CreateGLContext(flags, SurfaceCaps::Any(), false, aXDisplay,
     810           0 :                                          aXWindow, config, false, nullptr);
     811             : }
     812             : 
     813             : already_AddRefed<GLContext>
     814           0 : GLContextProviderGLX::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated)
     815             : {
     816           0 :     X11CompositorWidget* compWidget = aCompositorWidget->AsX11();
     817           0 :     MOZ_ASSERT(compWidget);
     818             : 
     819             :     return CreateForWidget(compWidget->XDisplay(),
     820             :                            compWidget->XWindow(),
     821           0 :                            compWidget->GetCompositorOptions().UseWebRender(),
     822           0 :                            aForceAccelerated);
     823             : }
     824             : 
     825             : already_AddRefed<GLContext>
     826           0 : GLContextProviderGLX::CreateForWindow(nsIWidget* aWidget,
     827             :                                       bool aWebRender,
     828             :                                       bool aForceAccelerated)
     829             : {
     830           0 :     Display* display = (Display*)aWidget->GetNativeData(NS_NATIVE_COMPOSITOR_DISPLAY);
     831           0 :     Window window = GET_NATIVE_WINDOW(aWidget);
     832             : 
     833             :     return CreateForWidget(display,
     834             :                            window,
     835             :                            aWebRender,
     836           0 :                            aForceAccelerated);
     837             : }
     838             : 
     839             : static bool
     840           0 : ChooseConfig(GLXLibrary* glx, Display* display, int screen, const SurfaceCaps& minCaps,
     841             :              ScopedXFree<GLXFBConfig>* const out_scopedConfigArr,
     842             :              GLXFBConfig* const out_config, int* const out_visid)
     843             : {
     844           0 :     ScopedXFree<GLXFBConfig>& scopedConfigArr = *out_scopedConfigArr;
     845             : 
     846           0 :     if (minCaps.antialias)
     847           0 :         return false;
     848             : 
     849             :     int attribs[] = {
     850             :         LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT,
     851             :         LOCAL_GLX_X_RENDERABLE, True,
     852             :         LOCAL_GLX_RED_SIZE, 8,
     853             :         LOCAL_GLX_GREEN_SIZE, 8,
     854             :         LOCAL_GLX_BLUE_SIZE, 8,
     855           0 :         LOCAL_GLX_ALPHA_SIZE, minCaps.alpha ? 8 : 0,
     856           0 :         LOCAL_GLX_DEPTH_SIZE, minCaps.depth ? 16 : 0,
     857           0 :         LOCAL_GLX_STENCIL_SIZE, minCaps.stencil ? 8 : 0,
     858             :         0
     859           0 :     };
     860             : 
     861           0 :     int numConfigs = 0;
     862           0 :     scopedConfigArr = glx->fChooseFBConfig(display, screen, attribs, &numConfigs);
     863           0 :     if (!scopedConfigArr || !numConfigs)
     864           0 :         return false;
     865             : 
     866             :     // Issues with glxChooseFBConfig selection and sorting:
     867             :     // * ALPHA_SIZE is sorted as 'largest total RGBA bits first'. If we don't request
     868             :     //   alpha bits, we'll probably get RGBA anyways, since 32 is more than 24.
     869             :     // * DEPTH_SIZE is sorted largest first, including for `0` inputs.
     870             :     // * STENCIL_SIZE is smallest first, but it might return `8` even though we ask for
     871             :     //   `0`.
     872             : 
     873             :     // For now, we don't care about these. We *will* care when we do XPixmap sharing.
     874             : 
     875           0 :     for (int i = 0; i < numConfigs; ++i) {
     876           0 :         GLXFBConfig curConfig = scopedConfigArr[i];
     877             : 
     878             :         int visid;
     879           0 :         if (glx->fGetFBConfigAttrib(display, curConfig, LOCAL_GLX_VISUAL_ID, &visid)
     880             :             != Success)
     881             :         {
     882           0 :             continue;
     883             :         }
     884             : 
     885           0 :         if (!visid)
     886           0 :             continue;
     887             : 
     888           0 :         *out_config = curConfig;
     889           0 :         *out_visid = visid;
     890           0 :         return true;
     891             :     }
     892             : 
     893           0 :     return false;
     894             : }
     895             : 
     896             : bool
     897           0 : GLContextGLX::FindFBConfigForWindow(Display* display, int screen, Window window,
     898             :                                     ScopedXFree<GLXFBConfig>* const out_scopedConfigArr,
     899             :                                     GLXFBConfig* const out_config, int* const out_visid,
     900             :                                     bool aWebRender)
     901             : {
     902           0 :     ScopedXFree<GLXFBConfig>& cfgs = *out_scopedConfigArr;
     903             :     int numConfigs;
     904             :     const int webrenderAttribs[] = {
     905             :         LOCAL_GLX_DEPTH_SIZE, 24,
     906             :         LOCAL_GLX_DOUBLEBUFFER, True,
     907             :         0
     908           0 :     };
     909             : 
     910           0 :     if (aWebRender) {
     911             :       cfgs = sGLXLibrary.fChooseFBConfig(display,
     912             :                                          screen,
     913             :                                          webrenderAttribs,
     914           0 :                                          &numConfigs);
     915             :     } else {
     916             :       cfgs = sGLXLibrary.fGetFBConfigs(display,
     917             :                                        screen,
     918           0 :                                        &numConfigs);
     919             :     }
     920             : 
     921           0 :     if (!cfgs) {
     922           0 :         NS_WARNING("[GLX] glXGetFBConfigs() failed");
     923           0 :         return false;
     924             :     }
     925           0 :     NS_ASSERTION(numConfigs > 0, "No FBConfigs found!");
     926             : 
     927             :     // XXX the visual ID is almost certainly the LOCAL_GLX_FBCONFIG_ID, so
     928             :     // we could probably do this first and replace the glXGetFBConfigs
     929             :     // with glXChooseConfigs.  Docs are sparklingly clear as always.
     930             :     XWindowAttributes windowAttrs;
     931           0 :     if (!XGetWindowAttributes(display, window, &windowAttrs)) {
     932           0 :         NS_WARNING("[GLX] XGetWindowAttributes() failed");
     933           0 :         return false;
     934             :     }
     935           0 :     const VisualID windowVisualID = XVisualIDFromVisual(windowAttrs.visual);
     936             : #ifdef DEBUG
     937           0 :     printf("[GLX] window %lx has VisualID 0x%lx\n", window, windowVisualID);
     938             : #endif
     939             : 
     940           0 :     if (aWebRender) {
     941           0 :         for (int i = 0; i < numConfigs; i++) {
     942           0 :             int visid = X11None;
     943           0 :             sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid);
     944           0 :             if (!visid) {
     945           0 :                 continue;
     946             :             }
     947             : 
     948             :             int depth;
     949             :             Visual* visual;
     950           0 :             FindVisualAndDepth(display, visid, &visual, &depth);
     951           0 :             if (depth == windowAttrs.depth &&
     952           0 :                 AreCompatibleVisuals(windowAttrs.visual, visual)) {
     953           0 :                 *out_config = cfgs[i];
     954           0 :                 *out_visid = visid;
     955           0 :                 return true;
     956             :             }
     957             :         }
     958             :     } else {
     959           0 :         for (int i = 0; i < numConfigs; i++) {
     960           0 :             int visid = X11None;
     961           0 :             sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid);
     962           0 :             if (!visid) {
     963           0 :                 continue;
     964             :             }
     965           0 :             if (sGLXLibrary.IsATI()) {
     966             :                 int depth;
     967             :                 Visual* visual;
     968           0 :                 FindVisualAndDepth(display, visid, &visual, &depth);
     969           0 :                 if (depth == windowAttrs.depth &&
     970           0 :                     AreCompatibleVisuals(windowAttrs.visual, visual)) {
     971           0 :                     *out_config = cfgs[i];
     972           0 :                     *out_visid = visid;
     973           0 :                     return true;
     974             :                 }
     975             :             } else {
     976           0 :                 if (windowVisualID == static_cast<VisualID>(visid)) {
     977           0 :                     *out_config = cfgs[i];
     978           0 :                     *out_visid = visid;
     979           0 :                     return true;
     980             :                 }
     981             :             }
     982             :         }
     983             :     }
     984             : 
     985           0 :     NS_WARNING("[GLX] Couldn't find a FBConfig matching window visual");
     986           0 :     return false;
     987             : }
     988             : 
     989             : static already_AddRefed<GLContextGLX>
     990           0 : CreateOffscreenPixmapContext(CreateContextFlags flags, const IntSize& size,
     991             :                              const SurfaceCaps& minCaps, nsACString* const out_failureId)
     992             : {
     993           0 :     GLXLibrary* glx = &sGLXLibrary;
     994           0 :     if (!glx->EnsureInitialized())
     995           0 :         return nullptr;
     996             : 
     997           0 :     Display* display = DefaultXDisplay();
     998           0 :     int screen = DefaultScreen(display);
     999             : 
    1000           0 :     ScopedXFree<GLXFBConfig> scopedConfigArr;
    1001             :     GLXFBConfig config;
    1002             :     int visid;
    1003           0 :     if (!ChooseConfig(glx, display, screen, minCaps, &scopedConfigArr, &config, &visid)) {
    1004           0 :         NS_WARNING("Failed to find a compatible config.");
    1005           0 :         return nullptr;
    1006             :     }
    1007             : 
    1008             :     Visual* visual;
    1009             :     int depth;
    1010           0 :     FindVisualAndDepth(display, visid, &visual, &depth);
    1011             : 
    1012           0 :     OffMainThreadScopedXErrorHandler xErrorHandler;
    1013           0 :     bool error = false;
    1014             : 
    1015           0 :     gfx::IntSize dummySize(16, 16);
    1016           0 :     RefPtr<gfxXlibSurface> surface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display),
    1017             :                                                             visual,
    1018           0 :                                                             dummySize);
    1019           0 :     if (surface->CairoStatus() != 0) {
    1020           0 :         mozilla::Unused << xErrorHandler.SyncAndGetError(display);
    1021           0 :         return nullptr;
    1022             :     }
    1023             : 
    1024             :     // Handle slightly different signature between glXCreatePixmap and
    1025             :     // its pre-GLX-1.3 extension equivalent (though given the ABI, we
    1026             :     // might not need to).
    1027           0 :     const auto drawable = surface->XDrawable();
    1028           0 :     const auto pixmap = glx->fCreatePixmap(display, config, drawable, nullptr);
    1029           0 :     if (pixmap == 0) {
    1030           0 :         error = true;
    1031             :     }
    1032             : 
    1033           0 :     bool serverError = xErrorHandler.SyncAndGetError(display);
    1034           0 :     if (error || serverError)
    1035           0 :         return nullptr;
    1036             : 
    1037             :     return GLContextGLX::CreateGLContext(flags, minCaps, true, display, pixmap, config,
    1038           0 :                                          true, surface);
    1039             : }
    1040             : 
    1041             : /*static*/ already_AddRefed<GLContext>
    1042           0 : GLContextProviderGLX::CreateHeadless(CreateContextFlags flags,
    1043             :                                      nsACString* const out_failureId)
    1044             : {
    1045           0 :     IntSize dummySize = IntSize(16, 16);
    1046           0 :     SurfaceCaps dummyCaps = SurfaceCaps::Any();
    1047           0 :     return CreateOffscreenPixmapContext(flags, dummySize, dummyCaps, out_failureId);
    1048             : }
    1049             : 
    1050             : /*static*/ already_AddRefed<GLContext>
    1051           0 : GLContextProviderGLX::CreateOffscreen(const IntSize& size,
    1052             :                                       const SurfaceCaps& minCaps,
    1053             :                                       CreateContextFlags flags,
    1054             :                                       nsACString* const out_failureId)
    1055             : {
    1056           0 :     SurfaceCaps minBackbufferCaps = minCaps;
    1057           0 :     if (minCaps.antialias) {
    1058           0 :         minBackbufferCaps.antialias = false;
    1059           0 :         minBackbufferCaps.depth = false;
    1060           0 :         minBackbufferCaps.stencil = false;
    1061             :     }
    1062             : 
    1063           0 :     RefPtr<GLContext> gl;
    1064           0 :     gl = CreateOffscreenPixmapContext(flags, size, minBackbufferCaps, out_failureId);
    1065           0 :     if (!gl)
    1066           0 :         return nullptr;
    1067             : 
    1068           0 :     if (!gl->InitOffscreen(size, minCaps)) {
    1069           0 :         *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_GLX_INIT");
    1070           0 :         return nullptr;
    1071             :     }
    1072             : 
    1073           0 :     return gl.forget();
    1074             : }
    1075             : 
    1076             : /*static*/ GLContext*
    1077           0 : GLContextProviderGLX::GetGlobalContext()
    1078             : {
    1079             :     // Context sharing not supported.
    1080           0 :     return nullptr;
    1081             : }
    1082             : 
    1083             : /*static*/ void
    1084           0 : GLContextProviderGLX::Shutdown()
    1085             : {
    1086           0 : }
    1087             : 
    1088             : } /* namespace gl */
    1089           9 : } /* namespace mozilla */
    1090             : 

Generated by: LCOV version 1.13